From f6968f3091a0ccc2b5730b8daf0c5b749d55659f Mon Sep 17 00:00:00 2001 From: Alex Szabo Date: Mon, 17 Jun 2024 10:42:47 +0200 Subject: [PATCH 001/127] [CI] Prevent duplicate serverless image build (#186164) ## Summary Only adds build_project.yml if there's not already a deploy_project.yml added through labels ## Context Based on the labeling logic, if we had `ci:build-serverless-image` and `ci:project-deploy-*`, the steps for building the docker image would be added twice. See: https://elastic.slack.com/archives/C0D8P2XK5/p1718268306523329 --- .buildkite/scripts/pipelines/pull_request/pipeline.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index 02011690a13c3..38ae590f18e0b 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -145,15 +145,14 @@ const getPipeline = (filename: string, removeSteps = true) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/fips.yml')); } - if (GITHUB_PR_LABELS.includes('ci:build-serverless-image')) { - pipeline.push(getPipeline('.buildkite/pipelines/pull_request/build_project.yml')); - } if ( GITHUB_PR_LABELS.includes('ci:project-deploy-elasticsearch') || GITHUB_PR_LABELS.includes('ci:project-deploy-observability') || GITHUB_PR_LABELS.includes('ci:project-deploy-security') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/deploy_project.yml')); + } else if (GITHUB_PR_LABELS.includes('ci:build-serverless-image')) { + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/build_project.yml')); } if ( From 34b052c12be929b6d223cdc5ec41cbcbc471442e Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Mon, 17 Jun 2024 03:25:09 -0600 Subject: [PATCH 002/127] Update nav-kibana-dev.docnav.json (#186192) Attempt to force a nav rebuild. --- .../performance/adding_custom_performance_metrics.mdx | 3 +-- nav-kibana-dev.docnav.json | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev_docs/tutorials/performance/adding_custom_performance_metrics.mdx b/dev_docs/tutorials/performance/adding_custom_performance_metrics.mdx index 4db207ad4aecb..1c1224c1c858a 100644 --- a/dev_docs/tutorials/performance/adding_custom_performance_metrics.mdx +++ b/dev_docs/tutorials/performance/adding_custom_performance_metrics.mdx @@ -3,7 +3,6 @@ id: kibDevTutorialAddingCustomPerformanceMetrics slug: /kibana-dev-docs/tutorial/performance/adding_custom_performance_metrics title: Adding Performance Metrics summary: Learn how to instrument your code and analyze performance -date: 2023-01-13 tags: ['kibana', 'onboarding', 'setup', 'performance', 'development', 'telemetry'] --- @@ -241,7 +240,7 @@ const MyApp = () => { if (fetchedData.status === 'success') { setData(fetchedData); - // Call onPageReady once the meaningful data has rendered and visible to the user + // Call onPageReady once the meaningful data has rendered and visible to the user onPageReady(); } diff --git a/nav-kibana-dev.docnav.json b/nav-kibana-dev.docnav.json index cfe16536856d0..60dcb5d054393 100644 --- a/nav-kibana-dev.docnav.json +++ b/nav-kibana-dev.docnav.json @@ -115,7 +115,8 @@ "label": "Tutorials", "items": [ { - "id": "kibDevTutorialAddingCustomPerformanceMetrics" + "id": "kibDevTutorialAddingCustomPerformanceMetrics", + "label": "Adding Performance Metrics" }, { "id": "kibDevTutorialSetupWindowsDevWSL" From f672297b140695f1c920c5a1b3bdce6fc812aceb Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 17 Jun 2024 12:37:32 +0200 Subject: [PATCH 003/127] [ES|QL] Fixes the overflow problem of the editor (#186166) ## Summary Partially addressed https://github.com/elastic/kibana/issues/166085 Fixes the overflow problem in in the inline editing flyout ![image (47)](https://github.com/elastic/kibana/assets/17003240/b3645b15-33dd-4180-8473-73e656c6371a) --- .../kbn-text-based-editor/src/text_based_languages_editor.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index dac1f609430b6..686f508cdac1e 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -696,6 +696,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ lightbulb: { enabled: false, }, + fixedOverflowWidgets: true, readOnly: isLoading || isDisabled || From 95e502cbe69a02797e0bd3859e2912348f6632f2 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:36:40 +0200 Subject: [PATCH 004/127] skip failing test suite (#186261) --- .../apps/discover_ml_uptime/ml/alert_flyout.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts index 58c72ef9d1a27..7802a25f53e2f 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts @@ -67,7 +67,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { let testJobId = ''; - describe('anomaly detection alert', function () { + // Failing: See https://github.com/elastic/kibana/issues/186261 + describe.skip('anomaly detection alert', function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ecommerce'); await ml.testResources.createDataViewIfNeeded('ft_ecommerce', 'order_date'); From 96024b8d40c2dd9878e253b1402c114c7cb07934 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:55:47 +0200 Subject: [PATCH 005/127] [ES|QL] Update grammars (#186262) This PR updates the ES|QL grammars (lexer and parser) to match the latest version in Elasticsearch. --------- Co-authored-by: Stratoula Kalafateli --- packages/kbn-esql-ast/src/antlr/esql_lexer.g4 | 5 + .../kbn-esql-ast/src/antlr/esql_lexer.interp | 5 +- .../kbn-esql-ast/src/antlr/esql_lexer.tokens | 129 +- packages/kbn-esql-ast/src/antlr/esql_lexer.ts | 1074 ++++++------- .../kbn-esql-ast/src/antlr/esql_parser.g4 | 7 +- .../kbn-esql-ast/src/antlr/esql_parser.interp | 5 +- .../kbn-esql-ast/src/antlr/esql_parser.tokens | 129 +- .../kbn-esql-ast/src/antlr/esql_parser.ts | 1331 +++++++++-------- .../src/antlr/esql_parser_listener.ts | 36 +- .../esql_validation_meta_tests.json | 46 +- .../src/validation/validation.test.ts | 34 +- 11 files changed, 1478 insertions(+), 1323 deletions(-) diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 b/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 index 39cb43b84d356..d7a4b88e6d5c5 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 @@ -166,6 +166,11 @@ ASTERISK : '*'; SLASH : '/'; PERCENT : '%'; +NAMED_OR_POSITIONAL_PARAM + : PARAM LETTER UNQUOTED_ID_BODY* + | PARAM DIGIT+ + ; + // Brackets are funny. We can happen upon a CLOSING_BRACKET in two ways - one // way is to start in an explain command which then shifts us to expression // mode. Thus, the two popModes on CLOSING_BRACKET. The other way could as diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.interp b/packages/kbn-esql-ast/src/antlr/esql_lexer.interp index df8215d1a0461..911e1371fd129 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.interp +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.interp @@ -68,6 +68,7 @@ null '/' '%' null +null ']' null null @@ -193,6 +194,7 @@ MINUS ASTERISK SLASH PERCENT +NAMED_OR_POSITIONAL_PARAM OPENING_BRACKET CLOSING_BRACKET UNQUOTED_IDENTIFIER @@ -331,6 +333,7 @@ MINUS ASTERISK SLASH PERCENT +NAMED_OR_POSITIONAL_PARAM OPENING_BRACKET CLOSING_BRACKET UNQUOTED_IDENTIFIER @@ -464,4 +467,4 @@ METRICS_MODE CLOSING_METRICS_MODE atn: -[4, 0, 123, 1404, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 4, 20, 565, 8, 20, 11, 20, 12, 20, 566, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 5, 21, 575, 8, 21, 10, 21, 12, 21, 578, 9, 21, 1, 21, 3, 21, 581, 8, 21, 1, 21, 3, 21, 584, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 593, 8, 22, 10, 22, 12, 22, 596, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 4, 23, 604, 8, 23, 11, 23, 12, 23, 605, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 3, 24, 613, 8, 24, 1, 25, 4, 25, 616, 8, 25, 11, 25, 12, 25, 617, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 657, 8, 36, 1, 36, 4, 36, 660, 8, 36, 11, 36, 12, 36, 661, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 3, 39, 671, 8, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 3, 41, 678, 8, 41, 1, 42, 1, 42, 1, 42, 5, 42, 683, 8, 42, 10, 42, 12, 42, 686, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 5, 42, 694, 8, 42, 10, 42, 12, 42, 697, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 3, 42, 704, 8, 42, 1, 42, 3, 42, 707, 8, 42, 3, 42, 709, 8, 42, 1, 43, 4, 43, 712, 8, 43, 11, 43, 12, 43, 713, 1, 44, 4, 44, 717, 8, 44, 11, 44, 12, 44, 718, 1, 44, 1, 44, 5, 44, 723, 8, 44, 10, 44, 12, 44, 726, 9, 44, 1, 44, 1, 44, 4, 44, 730, 8, 44, 11, 44, 12, 44, 731, 1, 44, 4, 44, 735, 8, 44, 11, 44, 12, 44, 736, 1, 44, 1, 44, 5, 44, 741, 8, 44, 10, 44, 12, 44, 744, 9, 44, 3, 44, 746, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 752, 8, 44, 11, 44, 12, 44, 753, 1, 44, 1, 44, 3, 44, 758, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 5, 82, 889, 8, 82, 10, 82, 12, 82, 892, 9, 82, 1, 82, 1, 82, 3, 82, 896, 8, 82, 1, 82, 4, 82, 899, 8, 82, 11, 82, 12, 82, 900, 3, 82, 903, 8, 82, 1, 83, 1, 83, 4, 83, 907, 8, 83, 11, 83, 12, 83, 908, 1, 83, 1, 83, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 3, 102, 994, 8, 102, 1, 103, 1, 103, 3, 103, 998, 8, 103, 1, 103, 5, 103, 1001, 8, 103, 10, 103, 12, 103, 1004, 9, 103, 1, 103, 1, 103, 3, 103, 1008, 8, 103, 1, 103, 4, 103, 1011, 8, 103, 11, 103, 12, 103, 1012, 3, 103, 1015, 8, 103, 1, 104, 1, 104, 4, 104, 1019, 8, 104, 11, 104, 12, 104, 1020, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 122, 4, 122, 1096, 8, 122, 11, 122, 12, 122, 1097, 1, 122, 1, 122, 3, 122, 1102, 8, 122, 1, 122, 4, 122, 1105, 8, 122, 11, 122, 12, 122, 1106, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 172, 1, 172, 1, 172, 1, 172, 1, 172, 4, 172, 1325, 8, 172, 11, 172, 12, 172, 1326, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 2, 594, 695, 0, 189, 16, 1, 18, 2, 20, 3, 22, 4, 24, 5, 26, 6, 28, 7, 30, 8, 32, 9, 34, 10, 36, 11, 38, 12, 40, 13, 42, 14, 44, 15, 46, 16, 48, 17, 50, 18, 52, 19, 54, 20, 56, 21, 58, 22, 60, 23, 62, 24, 64, 0, 66, 25, 68, 0, 70, 0, 72, 26, 74, 27, 76, 28, 78, 29, 80, 0, 82, 0, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100, 30, 102, 31, 104, 32, 106, 33, 108, 34, 110, 35, 112, 36, 114, 37, 116, 38, 118, 39, 120, 40, 122, 41, 124, 42, 126, 43, 128, 44, 130, 45, 132, 46, 134, 47, 136, 48, 138, 49, 140, 50, 142, 51, 144, 52, 146, 53, 148, 54, 150, 55, 152, 56, 154, 57, 156, 58, 158, 59, 160, 60, 162, 61, 164, 62, 166, 63, 168, 64, 170, 65, 172, 66, 174, 67, 176, 68, 178, 69, 180, 70, 182, 0, 184, 71, 186, 72, 188, 73, 190, 74, 192, 0, 194, 0, 196, 0, 198, 0, 200, 0, 202, 0, 204, 75, 206, 0, 208, 76, 210, 77, 212, 78, 214, 0, 216, 0, 218, 0, 220, 0, 222, 0, 224, 79, 226, 80, 228, 81, 230, 82, 232, 0, 234, 0, 236, 0, 238, 0, 240, 83, 242, 0, 244, 84, 246, 85, 248, 86, 250, 0, 252, 0, 254, 87, 256, 88, 258, 0, 260, 89, 262, 0, 264, 0, 266, 90, 268, 91, 270, 92, 272, 0, 274, 0, 276, 0, 278, 0, 280, 0, 282, 0, 284, 0, 286, 93, 288, 94, 290, 95, 292, 0, 294, 0, 296, 0, 298, 0, 300, 0, 302, 96, 304, 97, 306, 98, 308, 0, 310, 0, 312, 0, 314, 0, 316, 99, 318, 100, 320, 101, 322, 0, 324, 0, 326, 0, 328, 0, 330, 102, 332, 103, 334, 104, 336, 0, 338, 105, 340, 106, 342, 107, 344, 108, 346, 0, 348, 109, 350, 110, 352, 111, 354, 112, 356, 0, 358, 113, 360, 114, 362, 115, 364, 116, 366, 117, 368, 0, 370, 0, 372, 118, 374, 119, 376, 120, 378, 0, 380, 121, 382, 122, 384, 123, 386, 0, 388, 0, 390, 0, 392, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 35, 2, 0, 68, 68, 100, 100, 2, 0, 73, 73, 105, 105, 2, 0, 83, 83, 115, 115, 2, 0, 69, 69, 101, 101, 2, 0, 67, 67, 99, 99, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 78, 78, 110, 110, 2, 0, 72, 72, 104, 104, 2, 0, 86, 86, 118, 118, 2, 0, 65, 65, 97, 97, 2, 0, 76, 76, 108, 108, 2, 0, 88, 88, 120, 120, 2, 0, 70, 70, 102, 102, 2, 0, 77, 77, 109, 109, 2, 0, 71, 71, 103, 103, 2, 0, 75, 75, 107, 107, 2, 0, 85, 85, 117, 117, 2, 0, 87, 87, 119, 119, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 10, 0, 9, 10, 13, 13, 32, 32, 44, 44, 47, 47, 61, 61, 91, 91, 93, 93, 96, 96, 124, 124, 2, 0, 42, 42, 47, 47, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 78, 78, 82, 82, 84, 84, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 43, 43, 45, 45, 1, 0, 96, 96, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121, 121, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1427, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 1, 68, 1, 0, 0, 0, 1, 70, 1, 0, 0, 0, 1, 72, 1, 0, 0, 0, 1, 74, 1, 0, 0, 0, 1, 76, 1, 0, 0, 0, 2, 78, 1, 0, 0, 0, 2, 100, 1, 0, 0, 0, 2, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 112, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 2, 136, 1, 0, 0, 0, 2, 138, 1, 0, 0, 0, 2, 140, 1, 0, 0, 0, 2, 142, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 2, 146, 1, 0, 0, 0, 2, 148, 1, 0, 0, 0, 2, 150, 1, 0, 0, 0, 2, 152, 1, 0, 0, 0, 2, 154, 1, 0, 0, 0, 2, 156, 1, 0, 0, 0, 2, 158, 1, 0, 0, 0, 2, 160, 1, 0, 0, 0, 2, 162, 1, 0, 0, 0, 2, 164, 1, 0, 0, 0, 2, 166, 1, 0, 0, 0, 2, 168, 1, 0, 0, 0, 2, 170, 1, 0, 0, 0, 2, 172, 1, 0, 0, 0, 2, 174, 1, 0, 0, 0, 2, 176, 1, 0, 0, 0, 2, 178, 1, 0, 0, 0, 2, 180, 1, 0, 0, 0, 2, 184, 1, 0, 0, 0, 2, 186, 1, 0, 0, 0, 2, 188, 1, 0, 0, 0, 2, 190, 1, 0, 0, 0, 3, 192, 1, 0, 0, 0, 3, 194, 1, 0, 0, 0, 3, 196, 1, 0, 0, 0, 3, 198, 1, 0, 0, 0, 3, 200, 1, 0, 0, 0, 3, 202, 1, 0, 0, 0, 3, 204, 1, 0, 0, 0, 3, 206, 1, 0, 0, 0, 3, 208, 1, 0, 0, 0, 3, 210, 1, 0, 0, 0, 3, 212, 1, 0, 0, 0, 4, 214, 1, 0, 0, 0, 4, 216, 1, 0, 0, 0, 4, 218, 1, 0, 0, 0, 4, 224, 1, 0, 0, 0, 4, 226, 1, 0, 0, 0, 4, 228, 1, 0, 0, 0, 4, 230, 1, 0, 0, 0, 5, 232, 1, 0, 0, 0, 5, 234, 1, 0, 0, 0, 5, 236, 1, 0, 0, 0, 5, 238, 1, 0, 0, 0, 5, 240, 1, 0, 0, 0, 5, 242, 1, 0, 0, 0, 5, 244, 1, 0, 0, 0, 5, 246, 1, 0, 0, 0, 5, 248, 1, 0, 0, 0, 6, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 260, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 6, 264, 1, 0, 0, 0, 6, 266, 1, 0, 0, 0, 6, 268, 1, 0, 0, 0, 6, 270, 1, 0, 0, 0, 7, 272, 1, 0, 0, 0, 7, 274, 1, 0, 0, 0, 7, 276, 1, 0, 0, 0, 7, 278, 1, 0, 0, 0, 7, 280, 1, 0, 0, 0, 7, 282, 1, 0, 0, 0, 7, 284, 1, 0, 0, 0, 7, 286, 1, 0, 0, 0, 7, 288, 1, 0, 0, 0, 7, 290, 1, 0, 0, 0, 8, 292, 1, 0, 0, 0, 8, 294, 1, 0, 0, 0, 8, 296, 1, 0, 0, 0, 8, 298, 1, 0, 0, 0, 8, 300, 1, 0, 0, 0, 8, 302, 1, 0, 0, 0, 8, 304, 1, 0, 0, 0, 8, 306, 1, 0, 0, 0, 9, 308, 1, 0, 0, 0, 9, 310, 1, 0, 0, 0, 9, 312, 1, 0, 0, 0, 9, 314, 1, 0, 0, 0, 9, 316, 1, 0, 0, 0, 9, 318, 1, 0, 0, 0, 9, 320, 1, 0, 0, 0, 10, 322, 1, 0, 0, 0, 10, 324, 1, 0, 0, 0, 10, 326, 1, 0, 0, 0, 10, 328, 1, 0, 0, 0, 10, 330, 1, 0, 0, 0, 10, 332, 1, 0, 0, 0, 10, 334, 1, 0, 0, 0, 11, 336, 1, 0, 0, 0, 11, 338, 1, 0, 0, 0, 11, 340, 1, 0, 0, 0, 11, 342, 1, 0, 0, 0, 11, 344, 1, 0, 0, 0, 12, 346, 1, 0, 0, 0, 12, 348, 1, 0, 0, 0, 12, 350, 1, 0, 0, 0, 12, 352, 1, 0, 0, 0, 12, 354, 1, 0, 0, 0, 13, 356, 1, 0, 0, 0, 13, 358, 1, 0, 0, 0, 13, 360, 1, 0, 0, 0, 13, 362, 1, 0, 0, 0, 13, 364, 1, 0, 0, 0, 13, 366, 1, 0, 0, 0, 14, 368, 1, 0, 0, 0, 14, 370, 1, 0, 0, 0, 14, 372, 1, 0, 0, 0, 14, 374, 1, 0, 0, 0, 14, 376, 1, 0, 0, 0, 15, 378, 1, 0, 0, 0, 15, 380, 1, 0, 0, 0, 15, 382, 1, 0, 0, 0, 15, 384, 1, 0, 0, 0, 15, 386, 1, 0, 0, 0, 15, 388, 1, 0, 0, 0, 15, 390, 1, 0, 0, 0, 15, 392, 1, 0, 0, 0, 16, 394, 1, 0, 0, 0, 18, 404, 1, 0, 0, 0, 20, 411, 1, 0, 0, 0, 22, 420, 1, 0, 0, 0, 24, 427, 1, 0, 0, 0, 26, 437, 1, 0, 0, 0, 28, 444, 1, 0, 0, 0, 30, 451, 1, 0, 0, 0, 32, 465, 1, 0, 0, 0, 34, 472, 1, 0, 0, 0, 36, 480, 1, 0, 0, 0, 38, 489, 1, 0, 0, 0, 40, 496, 1, 0, 0, 0, 42, 506, 1, 0, 0, 0, 44, 518, 1, 0, 0, 0, 46, 527, 1, 0, 0, 0, 48, 533, 1, 0, 0, 0, 50, 540, 1, 0, 0, 0, 52, 547, 1, 0, 0, 0, 54, 555, 1, 0, 0, 0, 56, 564, 1, 0, 0, 0, 58, 570, 1, 0, 0, 0, 60, 587, 1, 0, 0, 0, 62, 603, 1, 0, 0, 0, 64, 612, 1, 0, 0, 0, 66, 615, 1, 0, 0, 0, 68, 619, 1, 0, 0, 0, 70, 624, 1, 0, 0, 0, 72, 629, 1, 0, 0, 0, 74, 633, 1, 0, 0, 0, 76, 637, 1, 0, 0, 0, 78, 641, 1, 0, 0, 0, 80, 645, 1, 0, 0, 0, 82, 647, 1, 0, 0, 0, 84, 649, 1, 0, 0, 0, 86, 652, 1, 0, 0, 0, 88, 654, 1, 0, 0, 0, 90, 663, 1, 0, 0, 0, 92, 665, 1, 0, 0, 0, 94, 670, 1, 0, 0, 0, 96, 672, 1, 0, 0, 0, 98, 677, 1, 0, 0, 0, 100, 708, 1, 0, 0, 0, 102, 711, 1, 0, 0, 0, 104, 757, 1, 0, 0, 0, 106, 759, 1, 0, 0, 0, 108, 762, 1, 0, 0, 0, 110, 766, 1, 0, 0, 0, 112, 770, 1, 0, 0, 0, 114, 772, 1, 0, 0, 0, 116, 775, 1, 0, 0, 0, 118, 777, 1, 0, 0, 0, 120, 782, 1, 0, 0, 0, 122, 784, 1, 0, 0, 0, 124, 790, 1, 0, 0, 0, 126, 796, 1, 0, 0, 0, 128, 801, 1, 0, 0, 0, 130, 803, 1, 0, 0, 0, 132, 806, 1, 0, 0, 0, 134, 809, 1, 0, 0, 0, 136, 814, 1, 0, 0, 0, 138, 818, 1, 0, 0, 0, 140, 823, 1, 0, 0, 0, 142, 829, 1, 0, 0, 0, 144, 832, 1, 0, 0, 0, 146, 834, 1, 0, 0, 0, 148, 840, 1, 0, 0, 0, 150, 842, 1, 0, 0, 0, 152, 847, 1, 0, 0, 0, 154, 850, 1, 0, 0, 0, 156, 853, 1, 0, 0, 0, 158, 856, 1, 0, 0, 0, 160, 858, 1, 0, 0, 0, 162, 861, 1, 0, 0, 0, 164, 863, 1, 0, 0, 0, 166, 866, 1, 0, 0, 0, 168, 868, 1, 0, 0, 0, 170, 870, 1, 0, 0, 0, 172, 872, 1, 0, 0, 0, 174, 874, 1, 0, 0, 0, 176, 876, 1, 0, 0, 0, 178, 881, 1, 0, 0, 0, 180, 902, 1, 0, 0, 0, 182, 904, 1, 0, 0, 0, 184, 912, 1, 0, 0, 0, 186, 914, 1, 0, 0, 0, 188, 918, 1, 0, 0, 0, 190, 922, 1, 0, 0, 0, 192, 926, 1, 0, 0, 0, 194, 931, 1, 0, 0, 0, 196, 935, 1, 0, 0, 0, 198, 939, 1, 0, 0, 0, 200, 943, 1, 0, 0, 0, 202, 947, 1, 0, 0, 0, 204, 951, 1, 0, 0, 0, 206, 960, 1, 0, 0, 0, 208, 964, 1, 0, 0, 0, 210, 968, 1, 0, 0, 0, 212, 972, 1, 0, 0, 0, 214, 976, 1, 0, 0, 0, 216, 981, 1, 0, 0, 0, 218, 985, 1, 0, 0, 0, 220, 993, 1, 0, 0, 0, 222, 1014, 1, 0, 0, 0, 224, 1018, 1, 0, 0, 0, 226, 1022, 1, 0, 0, 0, 228, 1026, 1, 0, 0, 0, 230, 1030, 1, 0, 0, 0, 232, 1034, 1, 0, 0, 0, 234, 1039, 1, 0, 0, 0, 236, 1043, 1, 0, 0, 0, 238, 1047, 1, 0, 0, 0, 240, 1051, 1, 0, 0, 0, 242, 1054, 1, 0, 0, 0, 244, 1058, 1, 0, 0, 0, 246, 1062, 1, 0, 0, 0, 248, 1066, 1, 0, 0, 0, 250, 1070, 1, 0, 0, 0, 252, 1075, 1, 0, 0, 0, 254, 1080, 1, 0, 0, 0, 256, 1085, 1, 0, 0, 0, 258, 1092, 1, 0, 0, 0, 260, 1101, 1, 0, 0, 0, 262, 1108, 1, 0, 0, 0, 264, 1112, 1, 0, 0, 0, 266, 1116, 1, 0, 0, 0, 268, 1120, 1, 0, 0, 0, 270, 1124, 1, 0, 0, 0, 272, 1128, 1, 0, 0, 0, 274, 1134, 1, 0, 0, 0, 276, 1138, 1, 0, 0, 0, 278, 1142, 1, 0, 0, 0, 280, 1146, 1, 0, 0, 0, 282, 1150, 1, 0, 0, 0, 284, 1154, 1, 0, 0, 0, 286, 1158, 1, 0, 0, 0, 288, 1162, 1, 0, 0, 0, 290, 1166, 1, 0, 0, 0, 292, 1170, 1, 0, 0, 0, 294, 1175, 1, 0, 0, 0, 296, 1179, 1, 0, 0, 0, 298, 1183, 1, 0, 0, 0, 300, 1188, 1, 0, 0, 0, 302, 1192, 1, 0, 0, 0, 304, 1196, 1, 0, 0, 0, 306, 1200, 1, 0, 0, 0, 308, 1204, 1, 0, 0, 0, 310, 1210, 1, 0, 0, 0, 312, 1214, 1, 0, 0, 0, 314, 1218, 1, 0, 0, 0, 316, 1222, 1, 0, 0, 0, 318, 1226, 1, 0, 0, 0, 320, 1230, 1, 0, 0, 0, 322, 1234, 1, 0, 0, 0, 324, 1239, 1, 0, 0, 0, 326, 1243, 1, 0, 0, 0, 328, 1247, 1, 0, 0, 0, 330, 1251, 1, 0, 0, 0, 332, 1255, 1, 0, 0, 0, 334, 1259, 1, 0, 0, 0, 336, 1263, 1, 0, 0, 0, 338, 1268, 1, 0, 0, 0, 340, 1273, 1, 0, 0, 0, 342, 1277, 1, 0, 0, 0, 344, 1281, 1, 0, 0, 0, 346, 1285, 1, 0, 0, 0, 348, 1290, 1, 0, 0, 0, 350, 1300, 1, 0, 0, 0, 352, 1304, 1, 0, 0, 0, 354, 1308, 1, 0, 0, 0, 356, 1312, 1, 0, 0, 0, 358, 1317, 1, 0, 0, 0, 360, 1324, 1, 0, 0, 0, 362, 1328, 1, 0, 0, 0, 364, 1332, 1, 0, 0, 0, 366, 1336, 1, 0, 0, 0, 368, 1340, 1, 0, 0, 0, 370, 1345, 1, 0, 0, 0, 372, 1351, 1, 0, 0, 0, 374, 1355, 1, 0, 0, 0, 376, 1359, 1, 0, 0, 0, 378, 1363, 1, 0, 0, 0, 380, 1369, 1, 0, 0, 0, 382, 1373, 1, 0, 0, 0, 384, 1377, 1, 0, 0, 0, 386, 1381, 1, 0, 0, 0, 388, 1387, 1, 0, 0, 0, 390, 1393, 1, 0, 0, 0, 392, 1399, 1, 0, 0, 0, 394, 395, 7, 0, 0, 0, 395, 396, 7, 1, 0, 0, 396, 397, 7, 2, 0, 0, 397, 398, 7, 2, 0, 0, 398, 399, 7, 3, 0, 0, 399, 400, 7, 4, 0, 0, 400, 401, 7, 5, 0, 0, 401, 402, 1, 0, 0, 0, 402, 403, 6, 0, 0, 0, 403, 17, 1, 0, 0, 0, 404, 405, 7, 0, 0, 0, 405, 406, 7, 6, 0, 0, 406, 407, 7, 7, 0, 0, 407, 408, 7, 8, 0, 0, 408, 409, 1, 0, 0, 0, 409, 410, 6, 1, 1, 0, 410, 19, 1, 0, 0, 0, 411, 412, 7, 3, 0, 0, 412, 413, 7, 9, 0, 0, 413, 414, 7, 6, 0, 0, 414, 415, 7, 1, 0, 0, 415, 416, 7, 4, 0, 0, 416, 417, 7, 10, 0, 0, 417, 418, 1, 0, 0, 0, 418, 419, 6, 2, 2, 0, 419, 21, 1, 0, 0, 0, 420, 421, 7, 3, 0, 0, 421, 422, 7, 11, 0, 0, 422, 423, 7, 12, 0, 0, 423, 424, 7, 13, 0, 0, 424, 425, 1, 0, 0, 0, 425, 426, 6, 3, 0, 0, 426, 23, 1, 0, 0, 0, 427, 428, 7, 3, 0, 0, 428, 429, 7, 14, 0, 0, 429, 430, 7, 8, 0, 0, 430, 431, 7, 13, 0, 0, 431, 432, 7, 12, 0, 0, 432, 433, 7, 1, 0, 0, 433, 434, 7, 9, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436, 6, 4, 3, 0, 436, 25, 1, 0, 0, 0, 437, 438, 7, 15, 0, 0, 438, 439, 7, 6, 0, 0, 439, 440, 7, 7, 0, 0, 440, 441, 7, 16, 0, 0, 441, 442, 1, 0, 0, 0, 442, 443, 6, 5, 4, 0, 443, 27, 1, 0, 0, 0, 444, 445, 7, 17, 0, 0, 445, 446, 7, 6, 0, 0, 446, 447, 7, 7, 0, 0, 447, 448, 7, 18, 0, 0, 448, 449, 1, 0, 0, 0, 449, 450, 6, 6, 0, 0, 450, 29, 1, 0, 0, 0, 451, 452, 7, 1, 0, 0, 452, 453, 7, 9, 0, 0, 453, 454, 7, 13, 0, 0, 454, 455, 7, 1, 0, 0, 455, 456, 7, 9, 0, 0, 456, 457, 7, 3, 0, 0, 457, 458, 7, 2, 0, 0, 458, 459, 7, 5, 0, 0, 459, 460, 7, 12, 0, 0, 460, 461, 7, 5, 0, 0, 461, 462, 7, 2, 0, 0, 462, 463, 1, 0, 0, 0, 463, 464, 6, 7, 0, 0, 464, 31, 1, 0, 0, 0, 465, 466, 7, 18, 0, 0, 466, 467, 7, 3, 0, 0, 467, 468, 7, 3, 0, 0, 468, 469, 7, 8, 0, 0, 469, 470, 1, 0, 0, 0, 470, 471, 6, 8, 1, 0, 471, 33, 1, 0, 0, 0, 472, 473, 7, 13, 0, 0, 473, 474, 7, 1, 0, 0, 474, 475, 7, 16, 0, 0, 475, 476, 7, 1, 0, 0, 476, 477, 7, 5, 0, 0, 477, 478, 1, 0, 0, 0, 478, 479, 6, 9, 0, 0, 479, 35, 1, 0, 0, 0, 480, 481, 7, 13, 0, 0, 481, 482, 7, 7, 0, 0, 482, 483, 7, 7, 0, 0, 483, 484, 7, 18, 0, 0, 484, 485, 7, 19, 0, 0, 485, 486, 7, 8, 0, 0, 486, 487, 1, 0, 0, 0, 487, 488, 6, 10, 5, 0, 488, 37, 1, 0, 0, 0, 489, 490, 7, 16, 0, 0, 490, 491, 7, 3, 0, 0, 491, 492, 7, 5, 0, 0, 492, 493, 7, 12, 0, 0, 493, 494, 1, 0, 0, 0, 494, 495, 6, 11, 6, 0, 495, 39, 1, 0, 0, 0, 496, 497, 7, 16, 0, 0, 497, 498, 7, 3, 0, 0, 498, 499, 7, 5, 0, 0, 499, 500, 7, 6, 0, 0, 500, 501, 7, 1, 0, 0, 501, 502, 7, 4, 0, 0, 502, 503, 7, 2, 0, 0, 503, 504, 1, 0, 0, 0, 504, 505, 6, 12, 7, 0, 505, 41, 1, 0, 0, 0, 506, 507, 7, 16, 0, 0, 507, 508, 7, 11, 0, 0, 508, 509, 5, 95, 0, 0, 509, 510, 7, 3, 0, 0, 510, 511, 7, 14, 0, 0, 511, 512, 7, 8, 0, 0, 512, 513, 7, 12, 0, 0, 513, 514, 7, 9, 0, 0, 514, 515, 7, 0, 0, 0, 515, 516, 1, 0, 0, 0, 516, 517, 6, 13, 8, 0, 517, 43, 1, 0, 0, 0, 518, 519, 7, 6, 0, 0, 519, 520, 7, 3, 0, 0, 520, 521, 7, 9, 0, 0, 521, 522, 7, 12, 0, 0, 522, 523, 7, 16, 0, 0, 523, 524, 7, 3, 0, 0, 524, 525, 1, 0, 0, 0, 525, 526, 6, 14, 9, 0, 526, 45, 1, 0, 0, 0, 527, 528, 7, 6, 0, 0, 528, 529, 7, 7, 0, 0, 529, 530, 7, 20, 0, 0, 530, 531, 1, 0, 0, 0, 531, 532, 6, 15, 0, 0, 532, 47, 1, 0, 0, 0, 533, 534, 7, 2, 0, 0, 534, 535, 7, 10, 0, 0, 535, 536, 7, 7, 0, 0, 536, 537, 7, 20, 0, 0, 537, 538, 1, 0, 0, 0, 538, 539, 6, 16, 10, 0, 539, 49, 1, 0, 0, 0, 540, 541, 7, 2, 0, 0, 541, 542, 7, 7, 0, 0, 542, 543, 7, 6, 0, 0, 543, 544, 7, 5, 0, 0, 544, 545, 1, 0, 0, 0, 545, 546, 6, 17, 0, 0, 546, 51, 1, 0, 0, 0, 547, 548, 7, 2, 0, 0, 548, 549, 7, 5, 0, 0, 549, 550, 7, 12, 0, 0, 550, 551, 7, 5, 0, 0, 551, 552, 7, 2, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 6, 18, 0, 0, 554, 53, 1, 0, 0, 0, 555, 556, 7, 20, 0, 0, 556, 557, 7, 10, 0, 0, 557, 558, 7, 3, 0, 0, 558, 559, 7, 6, 0, 0, 559, 560, 7, 3, 0, 0, 560, 561, 1, 0, 0, 0, 561, 562, 6, 19, 0, 0, 562, 55, 1, 0, 0, 0, 563, 565, 8, 21, 0, 0, 564, 563, 1, 0, 0, 0, 565, 566, 1, 0, 0, 0, 566, 564, 1, 0, 0, 0, 566, 567, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 569, 6, 20, 0, 0, 569, 57, 1, 0, 0, 0, 570, 571, 5, 47, 0, 0, 571, 572, 5, 47, 0, 0, 572, 576, 1, 0, 0, 0, 573, 575, 8, 22, 0, 0, 574, 573, 1, 0, 0, 0, 575, 578, 1, 0, 0, 0, 576, 574, 1, 0, 0, 0, 576, 577, 1, 0, 0, 0, 577, 580, 1, 0, 0, 0, 578, 576, 1, 0, 0, 0, 579, 581, 5, 13, 0, 0, 580, 579, 1, 0, 0, 0, 580, 581, 1, 0, 0, 0, 581, 583, 1, 0, 0, 0, 582, 584, 5, 10, 0, 0, 583, 582, 1, 0, 0, 0, 583, 584, 1, 0, 0, 0, 584, 585, 1, 0, 0, 0, 585, 586, 6, 21, 11, 0, 586, 59, 1, 0, 0, 0, 587, 588, 5, 47, 0, 0, 588, 589, 5, 42, 0, 0, 589, 594, 1, 0, 0, 0, 590, 593, 3, 60, 22, 0, 591, 593, 9, 0, 0, 0, 592, 590, 1, 0, 0, 0, 592, 591, 1, 0, 0, 0, 593, 596, 1, 0, 0, 0, 594, 595, 1, 0, 0, 0, 594, 592, 1, 0, 0, 0, 595, 597, 1, 0, 0, 0, 596, 594, 1, 0, 0, 0, 597, 598, 5, 42, 0, 0, 598, 599, 5, 47, 0, 0, 599, 600, 1, 0, 0, 0, 600, 601, 6, 22, 11, 0, 601, 61, 1, 0, 0, 0, 602, 604, 7, 23, 0, 0, 603, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 603, 1, 0, 0, 0, 605, 606, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 608, 6, 23, 11, 0, 608, 63, 1, 0, 0, 0, 609, 613, 8, 24, 0, 0, 610, 611, 5, 47, 0, 0, 611, 613, 8, 25, 0, 0, 612, 609, 1, 0, 0, 0, 612, 610, 1, 0, 0, 0, 613, 65, 1, 0, 0, 0, 614, 616, 3, 64, 24, 0, 615, 614, 1, 0, 0, 0, 616, 617, 1, 0, 0, 0, 617, 615, 1, 0, 0, 0, 617, 618, 1, 0, 0, 0, 618, 67, 1, 0, 0, 0, 619, 620, 3, 176, 80, 0, 620, 621, 1, 0, 0, 0, 621, 622, 6, 26, 12, 0, 622, 623, 6, 26, 13, 0, 623, 69, 1, 0, 0, 0, 624, 625, 3, 78, 31, 0, 625, 626, 1, 0, 0, 0, 626, 627, 6, 27, 14, 0, 627, 628, 6, 27, 15, 0, 628, 71, 1, 0, 0, 0, 629, 630, 3, 62, 23, 0, 630, 631, 1, 0, 0, 0, 631, 632, 6, 28, 11, 0, 632, 73, 1, 0, 0, 0, 633, 634, 3, 58, 21, 0, 634, 635, 1, 0, 0, 0, 635, 636, 6, 29, 11, 0, 636, 75, 1, 0, 0, 0, 637, 638, 3, 60, 22, 0, 638, 639, 1, 0, 0, 0, 639, 640, 6, 30, 11, 0, 640, 77, 1, 0, 0, 0, 641, 642, 5, 124, 0, 0, 642, 643, 1, 0, 0, 0, 643, 644, 6, 31, 15, 0, 644, 79, 1, 0, 0, 0, 645, 646, 7, 26, 0, 0, 646, 81, 1, 0, 0, 0, 647, 648, 7, 27, 0, 0, 648, 83, 1, 0, 0, 0, 649, 650, 5, 92, 0, 0, 650, 651, 7, 28, 0, 0, 651, 85, 1, 0, 0, 0, 652, 653, 8, 29, 0, 0, 653, 87, 1, 0, 0, 0, 654, 656, 7, 3, 0, 0, 655, 657, 7, 30, 0, 0, 656, 655, 1, 0, 0, 0, 656, 657, 1, 0, 0, 0, 657, 659, 1, 0, 0, 0, 658, 660, 3, 80, 32, 0, 659, 658, 1, 0, 0, 0, 660, 661, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 89, 1, 0, 0, 0, 663, 664, 5, 64, 0, 0, 664, 91, 1, 0, 0, 0, 665, 666, 5, 96, 0, 0, 666, 93, 1, 0, 0, 0, 667, 671, 8, 31, 0, 0, 668, 669, 5, 96, 0, 0, 669, 671, 5, 96, 0, 0, 670, 667, 1, 0, 0, 0, 670, 668, 1, 0, 0, 0, 671, 95, 1, 0, 0, 0, 672, 673, 5, 95, 0, 0, 673, 97, 1, 0, 0, 0, 674, 678, 3, 82, 33, 0, 675, 678, 3, 80, 32, 0, 676, 678, 3, 96, 40, 0, 677, 674, 1, 0, 0, 0, 677, 675, 1, 0, 0, 0, 677, 676, 1, 0, 0, 0, 678, 99, 1, 0, 0, 0, 679, 684, 5, 34, 0, 0, 680, 683, 3, 84, 34, 0, 681, 683, 3, 86, 35, 0, 682, 680, 1, 0, 0, 0, 682, 681, 1, 0, 0, 0, 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, 684, 685, 1, 0, 0, 0, 685, 687, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 687, 709, 5, 34, 0, 0, 688, 689, 5, 34, 0, 0, 689, 690, 5, 34, 0, 0, 690, 691, 5, 34, 0, 0, 691, 695, 1, 0, 0, 0, 692, 694, 8, 22, 0, 0, 693, 692, 1, 0, 0, 0, 694, 697, 1, 0, 0, 0, 695, 696, 1, 0, 0, 0, 695, 693, 1, 0, 0, 0, 696, 698, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 698, 699, 5, 34, 0, 0, 699, 700, 5, 34, 0, 0, 700, 701, 5, 34, 0, 0, 701, 703, 1, 0, 0, 0, 702, 704, 5, 34, 0, 0, 703, 702, 1, 0, 0, 0, 703, 704, 1, 0, 0, 0, 704, 706, 1, 0, 0, 0, 705, 707, 5, 34, 0, 0, 706, 705, 1, 0, 0, 0, 706, 707, 1, 0, 0, 0, 707, 709, 1, 0, 0, 0, 708, 679, 1, 0, 0, 0, 708, 688, 1, 0, 0, 0, 709, 101, 1, 0, 0, 0, 710, 712, 3, 80, 32, 0, 711, 710, 1, 0, 0, 0, 712, 713, 1, 0, 0, 0, 713, 711, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 714, 103, 1, 0, 0, 0, 715, 717, 3, 80, 32, 0, 716, 715, 1, 0, 0, 0, 717, 718, 1, 0, 0, 0, 718, 716, 1, 0, 0, 0, 718, 719, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 724, 3, 120, 52, 0, 721, 723, 3, 80, 32, 0, 722, 721, 1, 0, 0, 0, 723, 726, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 724, 725, 1, 0, 0, 0, 725, 758, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 727, 729, 3, 120, 52, 0, 728, 730, 3, 80, 32, 0, 729, 728, 1, 0, 0, 0, 730, 731, 1, 0, 0, 0, 731, 729, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 732, 758, 1, 0, 0, 0, 733, 735, 3, 80, 32, 0, 734, 733, 1, 0, 0, 0, 735, 736, 1, 0, 0, 0, 736, 734, 1, 0, 0, 0, 736, 737, 1, 0, 0, 0, 737, 745, 1, 0, 0, 0, 738, 742, 3, 120, 52, 0, 739, 741, 3, 80, 32, 0, 740, 739, 1, 0, 0, 0, 741, 744, 1, 0, 0, 0, 742, 740, 1, 0, 0, 0, 742, 743, 1, 0, 0, 0, 743, 746, 1, 0, 0, 0, 744, 742, 1, 0, 0, 0, 745, 738, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 748, 3, 88, 36, 0, 748, 758, 1, 0, 0, 0, 749, 751, 3, 120, 52, 0, 750, 752, 3, 80, 32, 0, 751, 750, 1, 0, 0, 0, 752, 753, 1, 0, 0, 0, 753, 751, 1, 0, 0, 0, 753, 754, 1, 0, 0, 0, 754, 755, 1, 0, 0, 0, 755, 756, 3, 88, 36, 0, 756, 758, 1, 0, 0, 0, 757, 716, 1, 0, 0, 0, 757, 727, 1, 0, 0, 0, 757, 734, 1, 0, 0, 0, 757, 749, 1, 0, 0, 0, 758, 105, 1, 0, 0, 0, 759, 760, 7, 32, 0, 0, 760, 761, 7, 33, 0, 0, 761, 107, 1, 0, 0, 0, 762, 763, 7, 12, 0, 0, 763, 764, 7, 9, 0, 0, 764, 765, 7, 0, 0, 0, 765, 109, 1, 0, 0, 0, 766, 767, 7, 12, 0, 0, 767, 768, 7, 2, 0, 0, 768, 769, 7, 4, 0, 0, 769, 111, 1, 0, 0, 0, 770, 771, 5, 61, 0, 0, 771, 113, 1, 0, 0, 0, 772, 773, 5, 58, 0, 0, 773, 774, 5, 58, 0, 0, 774, 115, 1, 0, 0, 0, 775, 776, 5, 44, 0, 0, 776, 117, 1, 0, 0, 0, 777, 778, 7, 0, 0, 0, 778, 779, 7, 3, 0, 0, 779, 780, 7, 2, 0, 0, 780, 781, 7, 4, 0, 0, 781, 119, 1, 0, 0, 0, 782, 783, 5, 46, 0, 0, 783, 121, 1, 0, 0, 0, 784, 785, 7, 15, 0, 0, 785, 786, 7, 12, 0, 0, 786, 787, 7, 13, 0, 0, 787, 788, 7, 2, 0, 0, 788, 789, 7, 3, 0, 0, 789, 123, 1, 0, 0, 0, 790, 791, 7, 15, 0, 0, 791, 792, 7, 1, 0, 0, 792, 793, 7, 6, 0, 0, 793, 794, 7, 2, 0, 0, 794, 795, 7, 5, 0, 0, 795, 125, 1, 0, 0, 0, 796, 797, 7, 13, 0, 0, 797, 798, 7, 12, 0, 0, 798, 799, 7, 2, 0, 0, 799, 800, 7, 5, 0, 0, 800, 127, 1, 0, 0, 0, 801, 802, 5, 40, 0, 0, 802, 129, 1, 0, 0, 0, 803, 804, 7, 1, 0, 0, 804, 805, 7, 9, 0, 0, 805, 131, 1, 0, 0, 0, 806, 807, 7, 1, 0, 0, 807, 808, 7, 2, 0, 0, 808, 133, 1, 0, 0, 0, 809, 810, 7, 13, 0, 0, 810, 811, 7, 1, 0, 0, 811, 812, 7, 18, 0, 0, 812, 813, 7, 3, 0, 0, 813, 135, 1, 0, 0, 0, 814, 815, 7, 9, 0, 0, 815, 816, 7, 7, 0, 0, 816, 817, 7, 5, 0, 0, 817, 137, 1, 0, 0, 0, 818, 819, 7, 9, 0, 0, 819, 820, 7, 19, 0, 0, 820, 821, 7, 13, 0, 0, 821, 822, 7, 13, 0, 0, 822, 139, 1, 0, 0, 0, 823, 824, 7, 9, 0, 0, 824, 825, 7, 19, 0, 0, 825, 826, 7, 13, 0, 0, 826, 827, 7, 13, 0, 0, 827, 828, 7, 2, 0, 0, 828, 141, 1, 0, 0, 0, 829, 830, 7, 7, 0, 0, 830, 831, 7, 6, 0, 0, 831, 143, 1, 0, 0, 0, 832, 833, 5, 63, 0, 0, 833, 145, 1, 0, 0, 0, 834, 835, 7, 6, 0, 0, 835, 836, 7, 13, 0, 0, 836, 837, 7, 1, 0, 0, 837, 838, 7, 18, 0, 0, 838, 839, 7, 3, 0, 0, 839, 147, 1, 0, 0, 0, 840, 841, 5, 41, 0, 0, 841, 149, 1, 0, 0, 0, 842, 843, 7, 5, 0, 0, 843, 844, 7, 6, 0, 0, 844, 845, 7, 19, 0, 0, 845, 846, 7, 3, 0, 0, 846, 151, 1, 0, 0, 0, 847, 848, 5, 61, 0, 0, 848, 849, 5, 61, 0, 0, 849, 153, 1, 0, 0, 0, 850, 851, 5, 61, 0, 0, 851, 852, 5, 126, 0, 0, 852, 155, 1, 0, 0, 0, 853, 854, 5, 33, 0, 0, 854, 855, 5, 61, 0, 0, 855, 157, 1, 0, 0, 0, 856, 857, 5, 60, 0, 0, 857, 159, 1, 0, 0, 0, 858, 859, 5, 60, 0, 0, 859, 860, 5, 61, 0, 0, 860, 161, 1, 0, 0, 0, 861, 862, 5, 62, 0, 0, 862, 163, 1, 0, 0, 0, 863, 864, 5, 62, 0, 0, 864, 865, 5, 61, 0, 0, 865, 165, 1, 0, 0, 0, 866, 867, 5, 43, 0, 0, 867, 167, 1, 0, 0, 0, 868, 869, 5, 45, 0, 0, 869, 169, 1, 0, 0, 0, 870, 871, 5, 42, 0, 0, 871, 171, 1, 0, 0, 0, 872, 873, 5, 47, 0, 0, 873, 173, 1, 0, 0, 0, 874, 875, 5, 37, 0, 0, 875, 175, 1, 0, 0, 0, 876, 877, 5, 91, 0, 0, 877, 878, 1, 0, 0, 0, 878, 879, 6, 80, 0, 0, 879, 880, 6, 80, 0, 0, 880, 177, 1, 0, 0, 0, 881, 882, 5, 93, 0, 0, 882, 883, 1, 0, 0, 0, 883, 884, 6, 81, 15, 0, 884, 885, 6, 81, 15, 0, 885, 179, 1, 0, 0, 0, 886, 890, 3, 82, 33, 0, 887, 889, 3, 98, 41, 0, 888, 887, 1, 0, 0, 0, 889, 892, 1, 0, 0, 0, 890, 888, 1, 0, 0, 0, 890, 891, 1, 0, 0, 0, 891, 903, 1, 0, 0, 0, 892, 890, 1, 0, 0, 0, 893, 896, 3, 96, 40, 0, 894, 896, 3, 90, 37, 0, 895, 893, 1, 0, 0, 0, 895, 894, 1, 0, 0, 0, 896, 898, 1, 0, 0, 0, 897, 899, 3, 98, 41, 0, 898, 897, 1, 0, 0, 0, 899, 900, 1, 0, 0, 0, 900, 898, 1, 0, 0, 0, 900, 901, 1, 0, 0, 0, 901, 903, 1, 0, 0, 0, 902, 886, 1, 0, 0, 0, 902, 895, 1, 0, 0, 0, 903, 181, 1, 0, 0, 0, 904, 906, 3, 92, 38, 0, 905, 907, 3, 94, 39, 0, 906, 905, 1, 0, 0, 0, 907, 908, 1, 0, 0, 0, 908, 906, 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 910, 1, 0, 0, 0, 910, 911, 3, 92, 38, 0, 911, 183, 1, 0, 0, 0, 912, 913, 3, 182, 83, 0, 913, 185, 1, 0, 0, 0, 914, 915, 3, 58, 21, 0, 915, 916, 1, 0, 0, 0, 916, 917, 6, 85, 11, 0, 917, 187, 1, 0, 0, 0, 918, 919, 3, 60, 22, 0, 919, 920, 1, 0, 0, 0, 920, 921, 6, 86, 11, 0, 921, 189, 1, 0, 0, 0, 922, 923, 3, 62, 23, 0, 923, 924, 1, 0, 0, 0, 924, 925, 6, 87, 11, 0, 925, 191, 1, 0, 0, 0, 926, 927, 3, 78, 31, 0, 927, 928, 1, 0, 0, 0, 928, 929, 6, 88, 14, 0, 929, 930, 6, 88, 15, 0, 930, 193, 1, 0, 0, 0, 931, 932, 3, 176, 80, 0, 932, 933, 1, 0, 0, 0, 933, 934, 6, 89, 12, 0, 934, 195, 1, 0, 0, 0, 935, 936, 3, 178, 81, 0, 936, 937, 1, 0, 0, 0, 937, 938, 6, 90, 16, 0, 938, 197, 1, 0, 0, 0, 939, 940, 3, 116, 50, 0, 940, 941, 1, 0, 0, 0, 941, 942, 6, 91, 17, 0, 942, 199, 1, 0, 0, 0, 943, 944, 3, 112, 48, 0, 944, 945, 1, 0, 0, 0, 945, 946, 6, 92, 18, 0, 946, 201, 1, 0, 0, 0, 947, 948, 3, 100, 42, 0, 948, 949, 1, 0, 0, 0, 949, 950, 6, 93, 19, 0, 950, 203, 1, 0, 0, 0, 951, 952, 7, 16, 0, 0, 952, 953, 7, 3, 0, 0, 953, 954, 7, 5, 0, 0, 954, 955, 7, 12, 0, 0, 955, 956, 7, 0, 0, 0, 956, 957, 7, 12, 0, 0, 957, 958, 7, 5, 0, 0, 958, 959, 7, 12, 0, 0, 959, 205, 1, 0, 0, 0, 960, 961, 3, 66, 25, 0, 961, 962, 1, 0, 0, 0, 962, 963, 6, 95, 20, 0, 963, 207, 1, 0, 0, 0, 964, 965, 3, 58, 21, 0, 965, 966, 1, 0, 0, 0, 966, 967, 6, 96, 11, 0, 967, 209, 1, 0, 0, 0, 968, 969, 3, 60, 22, 0, 969, 970, 1, 0, 0, 0, 970, 971, 6, 97, 11, 0, 971, 211, 1, 0, 0, 0, 972, 973, 3, 62, 23, 0, 973, 974, 1, 0, 0, 0, 974, 975, 6, 98, 11, 0, 975, 213, 1, 0, 0, 0, 976, 977, 3, 78, 31, 0, 977, 978, 1, 0, 0, 0, 978, 979, 6, 99, 14, 0, 979, 980, 6, 99, 15, 0, 980, 215, 1, 0, 0, 0, 981, 982, 3, 120, 52, 0, 982, 983, 1, 0, 0, 0, 983, 984, 6, 100, 21, 0, 984, 217, 1, 0, 0, 0, 985, 986, 3, 116, 50, 0, 986, 987, 1, 0, 0, 0, 987, 988, 6, 101, 17, 0, 988, 219, 1, 0, 0, 0, 989, 994, 3, 82, 33, 0, 990, 994, 3, 80, 32, 0, 991, 994, 3, 96, 40, 0, 992, 994, 3, 170, 77, 0, 993, 989, 1, 0, 0, 0, 993, 990, 1, 0, 0, 0, 993, 991, 1, 0, 0, 0, 993, 992, 1, 0, 0, 0, 994, 221, 1, 0, 0, 0, 995, 998, 3, 82, 33, 0, 996, 998, 3, 170, 77, 0, 997, 995, 1, 0, 0, 0, 997, 996, 1, 0, 0, 0, 998, 1002, 1, 0, 0, 0, 999, 1001, 3, 220, 102, 0, 1000, 999, 1, 0, 0, 0, 1001, 1004, 1, 0, 0, 0, 1002, 1000, 1, 0, 0, 0, 1002, 1003, 1, 0, 0, 0, 1003, 1015, 1, 0, 0, 0, 1004, 1002, 1, 0, 0, 0, 1005, 1008, 3, 96, 40, 0, 1006, 1008, 3, 90, 37, 0, 1007, 1005, 1, 0, 0, 0, 1007, 1006, 1, 0, 0, 0, 1008, 1010, 1, 0, 0, 0, 1009, 1011, 3, 220, 102, 0, 1010, 1009, 1, 0, 0, 0, 1011, 1012, 1, 0, 0, 0, 1012, 1010, 1, 0, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1015, 1, 0, 0, 0, 1014, 997, 1, 0, 0, 0, 1014, 1007, 1, 0, 0, 0, 1015, 223, 1, 0, 0, 0, 1016, 1019, 3, 222, 103, 0, 1017, 1019, 3, 182, 83, 0, 1018, 1016, 1, 0, 0, 0, 1018, 1017, 1, 0, 0, 0, 1019, 1020, 1, 0, 0, 0, 1020, 1018, 1, 0, 0, 0, 1020, 1021, 1, 0, 0, 0, 1021, 225, 1, 0, 0, 0, 1022, 1023, 3, 58, 21, 0, 1023, 1024, 1, 0, 0, 0, 1024, 1025, 6, 105, 11, 0, 1025, 227, 1, 0, 0, 0, 1026, 1027, 3, 60, 22, 0, 1027, 1028, 1, 0, 0, 0, 1028, 1029, 6, 106, 11, 0, 1029, 229, 1, 0, 0, 0, 1030, 1031, 3, 62, 23, 0, 1031, 1032, 1, 0, 0, 0, 1032, 1033, 6, 107, 11, 0, 1033, 231, 1, 0, 0, 0, 1034, 1035, 3, 78, 31, 0, 1035, 1036, 1, 0, 0, 0, 1036, 1037, 6, 108, 14, 0, 1037, 1038, 6, 108, 15, 0, 1038, 233, 1, 0, 0, 0, 1039, 1040, 3, 112, 48, 0, 1040, 1041, 1, 0, 0, 0, 1041, 1042, 6, 109, 18, 0, 1042, 235, 1, 0, 0, 0, 1043, 1044, 3, 116, 50, 0, 1044, 1045, 1, 0, 0, 0, 1045, 1046, 6, 110, 17, 0, 1046, 237, 1, 0, 0, 0, 1047, 1048, 3, 120, 52, 0, 1048, 1049, 1, 0, 0, 0, 1049, 1050, 6, 111, 21, 0, 1050, 239, 1, 0, 0, 0, 1051, 1052, 7, 12, 0, 0, 1052, 1053, 7, 2, 0, 0, 1053, 241, 1, 0, 0, 0, 1054, 1055, 3, 224, 104, 0, 1055, 1056, 1, 0, 0, 0, 1056, 1057, 6, 113, 22, 0, 1057, 243, 1, 0, 0, 0, 1058, 1059, 3, 58, 21, 0, 1059, 1060, 1, 0, 0, 0, 1060, 1061, 6, 114, 11, 0, 1061, 245, 1, 0, 0, 0, 1062, 1063, 3, 60, 22, 0, 1063, 1064, 1, 0, 0, 0, 1064, 1065, 6, 115, 11, 0, 1065, 247, 1, 0, 0, 0, 1066, 1067, 3, 62, 23, 0, 1067, 1068, 1, 0, 0, 0, 1068, 1069, 6, 116, 11, 0, 1069, 249, 1, 0, 0, 0, 1070, 1071, 3, 78, 31, 0, 1071, 1072, 1, 0, 0, 0, 1072, 1073, 6, 117, 14, 0, 1073, 1074, 6, 117, 15, 0, 1074, 251, 1, 0, 0, 0, 1075, 1076, 3, 176, 80, 0, 1076, 1077, 1, 0, 0, 0, 1077, 1078, 6, 118, 12, 0, 1078, 1079, 6, 118, 23, 0, 1079, 253, 1, 0, 0, 0, 1080, 1081, 7, 7, 0, 0, 1081, 1082, 7, 9, 0, 0, 1082, 1083, 1, 0, 0, 0, 1083, 1084, 6, 119, 24, 0, 1084, 255, 1, 0, 0, 0, 1085, 1086, 7, 20, 0, 0, 1086, 1087, 7, 1, 0, 0, 1087, 1088, 7, 5, 0, 0, 1088, 1089, 7, 10, 0, 0, 1089, 1090, 1, 0, 0, 0, 1090, 1091, 6, 120, 24, 0, 1091, 257, 1, 0, 0, 0, 1092, 1093, 8, 34, 0, 0, 1093, 259, 1, 0, 0, 0, 1094, 1096, 3, 258, 121, 0, 1095, 1094, 1, 0, 0, 0, 1096, 1097, 1, 0, 0, 0, 1097, 1095, 1, 0, 0, 0, 1097, 1098, 1, 0, 0, 0, 1098, 1099, 1, 0, 0, 0, 1099, 1100, 3, 358, 171, 0, 1100, 1102, 1, 0, 0, 0, 1101, 1095, 1, 0, 0, 0, 1101, 1102, 1, 0, 0, 0, 1102, 1104, 1, 0, 0, 0, 1103, 1105, 3, 258, 121, 0, 1104, 1103, 1, 0, 0, 0, 1105, 1106, 1, 0, 0, 0, 1106, 1104, 1, 0, 0, 0, 1106, 1107, 1, 0, 0, 0, 1107, 261, 1, 0, 0, 0, 1108, 1109, 3, 184, 84, 0, 1109, 1110, 1, 0, 0, 0, 1110, 1111, 6, 123, 25, 0, 1111, 263, 1, 0, 0, 0, 1112, 1113, 3, 260, 122, 0, 1113, 1114, 1, 0, 0, 0, 1114, 1115, 6, 124, 26, 0, 1115, 265, 1, 0, 0, 0, 1116, 1117, 3, 58, 21, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1119, 6, 125, 11, 0, 1119, 267, 1, 0, 0, 0, 1120, 1121, 3, 60, 22, 0, 1121, 1122, 1, 0, 0, 0, 1122, 1123, 6, 126, 11, 0, 1123, 269, 1, 0, 0, 0, 1124, 1125, 3, 62, 23, 0, 1125, 1126, 1, 0, 0, 0, 1126, 1127, 6, 127, 11, 0, 1127, 271, 1, 0, 0, 0, 1128, 1129, 3, 78, 31, 0, 1129, 1130, 1, 0, 0, 0, 1130, 1131, 6, 128, 14, 0, 1131, 1132, 6, 128, 15, 0, 1132, 1133, 6, 128, 15, 0, 1133, 273, 1, 0, 0, 0, 1134, 1135, 3, 112, 48, 0, 1135, 1136, 1, 0, 0, 0, 1136, 1137, 6, 129, 18, 0, 1137, 275, 1, 0, 0, 0, 1138, 1139, 3, 116, 50, 0, 1139, 1140, 1, 0, 0, 0, 1140, 1141, 6, 130, 17, 0, 1141, 277, 1, 0, 0, 0, 1142, 1143, 3, 120, 52, 0, 1143, 1144, 1, 0, 0, 0, 1144, 1145, 6, 131, 21, 0, 1145, 279, 1, 0, 0, 0, 1146, 1147, 3, 256, 120, 0, 1147, 1148, 1, 0, 0, 0, 1148, 1149, 6, 132, 27, 0, 1149, 281, 1, 0, 0, 0, 1150, 1151, 3, 224, 104, 0, 1151, 1152, 1, 0, 0, 0, 1152, 1153, 6, 133, 22, 0, 1153, 283, 1, 0, 0, 0, 1154, 1155, 3, 184, 84, 0, 1155, 1156, 1, 0, 0, 0, 1156, 1157, 6, 134, 25, 0, 1157, 285, 1, 0, 0, 0, 1158, 1159, 3, 58, 21, 0, 1159, 1160, 1, 0, 0, 0, 1160, 1161, 6, 135, 11, 0, 1161, 287, 1, 0, 0, 0, 1162, 1163, 3, 60, 22, 0, 1163, 1164, 1, 0, 0, 0, 1164, 1165, 6, 136, 11, 0, 1165, 289, 1, 0, 0, 0, 1166, 1167, 3, 62, 23, 0, 1167, 1168, 1, 0, 0, 0, 1168, 1169, 6, 137, 11, 0, 1169, 291, 1, 0, 0, 0, 1170, 1171, 3, 78, 31, 0, 1171, 1172, 1, 0, 0, 0, 1172, 1173, 6, 138, 14, 0, 1173, 1174, 6, 138, 15, 0, 1174, 293, 1, 0, 0, 0, 1175, 1176, 3, 116, 50, 0, 1176, 1177, 1, 0, 0, 0, 1177, 1178, 6, 139, 17, 0, 1178, 295, 1, 0, 0, 0, 1179, 1180, 3, 120, 52, 0, 1180, 1181, 1, 0, 0, 0, 1181, 1182, 6, 140, 21, 0, 1182, 297, 1, 0, 0, 0, 1183, 1184, 3, 254, 119, 0, 1184, 1185, 1, 0, 0, 0, 1185, 1186, 6, 141, 28, 0, 1186, 1187, 6, 141, 29, 0, 1187, 299, 1, 0, 0, 0, 1188, 1189, 3, 66, 25, 0, 1189, 1190, 1, 0, 0, 0, 1190, 1191, 6, 142, 20, 0, 1191, 301, 1, 0, 0, 0, 1192, 1193, 3, 58, 21, 0, 1193, 1194, 1, 0, 0, 0, 1194, 1195, 6, 143, 11, 0, 1195, 303, 1, 0, 0, 0, 1196, 1197, 3, 60, 22, 0, 1197, 1198, 1, 0, 0, 0, 1198, 1199, 6, 144, 11, 0, 1199, 305, 1, 0, 0, 0, 1200, 1201, 3, 62, 23, 0, 1201, 1202, 1, 0, 0, 0, 1202, 1203, 6, 145, 11, 0, 1203, 307, 1, 0, 0, 0, 1204, 1205, 3, 78, 31, 0, 1205, 1206, 1, 0, 0, 0, 1206, 1207, 6, 146, 14, 0, 1207, 1208, 6, 146, 15, 0, 1208, 1209, 6, 146, 15, 0, 1209, 309, 1, 0, 0, 0, 1210, 1211, 3, 116, 50, 0, 1211, 1212, 1, 0, 0, 0, 1212, 1213, 6, 147, 17, 0, 1213, 311, 1, 0, 0, 0, 1214, 1215, 3, 120, 52, 0, 1215, 1216, 1, 0, 0, 0, 1216, 1217, 6, 148, 21, 0, 1217, 313, 1, 0, 0, 0, 1218, 1219, 3, 224, 104, 0, 1219, 1220, 1, 0, 0, 0, 1220, 1221, 6, 149, 22, 0, 1221, 315, 1, 0, 0, 0, 1222, 1223, 3, 58, 21, 0, 1223, 1224, 1, 0, 0, 0, 1224, 1225, 6, 150, 11, 0, 1225, 317, 1, 0, 0, 0, 1226, 1227, 3, 60, 22, 0, 1227, 1228, 1, 0, 0, 0, 1228, 1229, 6, 151, 11, 0, 1229, 319, 1, 0, 0, 0, 1230, 1231, 3, 62, 23, 0, 1231, 1232, 1, 0, 0, 0, 1232, 1233, 6, 152, 11, 0, 1233, 321, 1, 0, 0, 0, 1234, 1235, 3, 78, 31, 0, 1235, 1236, 1, 0, 0, 0, 1236, 1237, 6, 153, 14, 0, 1237, 1238, 6, 153, 15, 0, 1238, 323, 1, 0, 0, 0, 1239, 1240, 3, 120, 52, 0, 1240, 1241, 1, 0, 0, 0, 1241, 1242, 6, 154, 21, 0, 1242, 325, 1, 0, 0, 0, 1243, 1244, 3, 184, 84, 0, 1244, 1245, 1, 0, 0, 0, 1245, 1246, 6, 155, 25, 0, 1246, 327, 1, 0, 0, 0, 1247, 1248, 3, 180, 82, 0, 1248, 1249, 1, 0, 0, 0, 1249, 1250, 6, 156, 30, 0, 1250, 329, 1, 0, 0, 0, 1251, 1252, 3, 58, 21, 0, 1252, 1253, 1, 0, 0, 0, 1253, 1254, 6, 157, 11, 0, 1254, 331, 1, 0, 0, 0, 1255, 1256, 3, 60, 22, 0, 1256, 1257, 1, 0, 0, 0, 1257, 1258, 6, 158, 11, 0, 1258, 333, 1, 0, 0, 0, 1259, 1260, 3, 62, 23, 0, 1260, 1261, 1, 0, 0, 0, 1261, 1262, 6, 159, 11, 0, 1262, 335, 1, 0, 0, 0, 1263, 1264, 3, 78, 31, 0, 1264, 1265, 1, 0, 0, 0, 1265, 1266, 6, 160, 14, 0, 1266, 1267, 6, 160, 15, 0, 1267, 337, 1, 0, 0, 0, 1268, 1269, 7, 1, 0, 0, 1269, 1270, 7, 9, 0, 0, 1270, 1271, 7, 15, 0, 0, 1271, 1272, 7, 7, 0, 0, 1272, 339, 1, 0, 0, 0, 1273, 1274, 3, 58, 21, 0, 1274, 1275, 1, 0, 0, 0, 1275, 1276, 6, 162, 11, 0, 1276, 341, 1, 0, 0, 0, 1277, 1278, 3, 60, 22, 0, 1278, 1279, 1, 0, 0, 0, 1279, 1280, 6, 163, 11, 0, 1280, 343, 1, 0, 0, 0, 1281, 1282, 3, 62, 23, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1284, 6, 164, 11, 0, 1284, 345, 1, 0, 0, 0, 1285, 1286, 3, 78, 31, 0, 1286, 1287, 1, 0, 0, 0, 1287, 1288, 6, 165, 14, 0, 1288, 1289, 6, 165, 15, 0, 1289, 347, 1, 0, 0, 0, 1290, 1291, 7, 15, 0, 0, 1291, 1292, 7, 19, 0, 0, 1292, 1293, 7, 9, 0, 0, 1293, 1294, 7, 4, 0, 0, 1294, 1295, 7, 5, 0, 0, 1295, 1296, 7, 1, 0, 0, 1296, 1297, 7, 7, 0, 0, 1297, 1298, 7, 9, 0, 0, 1298, 1299, 7, 2, 0, 0, 1299, 349, 1, 0, 0, 0, 1300, 1301, 3, 58, 21, 0, 1301, 1302, 1, 0, 0, 0, 1302, 1303, 6, 167, 11, 0, 1303, 351, 1, 0, 0, 0, 1304, 1305, 3, 60, 22, 0, 1305, 1306, 1, 0, 0, 0, 1306, 1307, 6, 168, 11, 0, 1307, 353, 1, 0, 0, 0, 1308, 1309, 3, 62, 23, 0, 1309, 1310, 1, 0, 0, 0, 1310, 1311, 6, 169, 11, 0, 1311, 355, 1, 0, 0, 0, 1312, 1313, 3, 178, 81, 0, 1313, 1314, 1, 0, 0, 0, 1314, 1315, 6, 170, 16, 0, 1315, 1316, 6, 170, 15, 0, 1316, 357, 1, 0, 0, 0, 1317, 1318, 5, 58, 0, 0, 1318, 359, 1, 0, 0, 0, 1319, 1325, 3, 90, 37, 0, 1320, 1325, 3, 80, 32, 0, 1321, 1325, 3, 120, 52, 0, 1322, 1325, 3, 82, 33, 0, 1323, 1325, 3, 96, 40, 0, 1324, 1319, 1, 0, 0, 0, 1324, 1320, 1, 0, 0, 0, 1324, 1321, 1, 0, 0, 0, 1324, 1322, 1, 0, 0, 0, 1324, 1323, 1, 0, 0, 0, 1325, 1326, 1, 0, 0, 0, 1326, 1324, 1, 0, 0, 0, 1326, 1327, 1, 0, 0, 0, 1327, 361, 1, 0, 0, 0, 1328, 1329, 3, 58, 21, 0, 1329, 1330, 1, 0, 0, 0, 1330, 1331, 6, 173, 11, 0, 1331, 363, 1, 0, 0, 0, 1332, 1333, 3, 60, 22, 0, 1333, 1334, 1, 0, 0, 0, 1334, 1335, 6, 174, 11, 0, 1335, 365, 1, 0, 0, 0, 1336, 1337, 3, 62, 23, 0, 1337, 1338, 1, 0, 0, 0, 1338, 1339, 6, 175, 11, 0, 1339, 367, 1, 0, 0, 0, 1340, 1341, 3, 78, 31, 0, 1341, 1342, 1, 0, 0, 0, 1342, 1343, 6, 176, 14, 0, 1343, 1344, 6, 176, 15, 0, 1344, 369, 1, 0, 0, 0, 1345, 1346, 3, 66, 25, 0, 1346, 1347, 1, 0, 0, 0, 1347, 1348, 6, 177, 20, 0, 1348, 1349, 6, 177, 15, 0, 1349, 1350, 6, 177, 31, 0, 1350, 371, 1, 0, 0, 0, 1351, 1352, 3, 58, 21, 0, 1352, 1353, 1, 0, 0, 0, 1353, 1354, 6, 178, 11, 0, 1354, 373, 1, 0, 0, 0, 1355, 1356, 3, 60, 22, 0, 1356, 1357, 1, 0, 0, 0, 1357, 1358, 6, 179, 11, 0, 1358, 375, 1, 0, 0, 0, 1359, 1360, 3, 62, 23, 0, 1360, 1361, 1, 0, 0, 0, 1361, 1362, 6, 180, 11, 0, 1362, 377, 1, 0, 0, 0, 1363, 1364, 3, 116, 50, 0, 1364, 1365, 1, 0, 0, 0, 1365, 1366, 6, 181, 17, 0, 1366, 1367, 6, 181, 15, 0, 1367, 1368, 6, 181, 7, 0, 1368, 379, 1, 0, 0, 0, 1369, 1370, 3, 58, 21, 0, 1370, 1371, 1, 0, 0, 0, 1371, 1372, 6, 182, 11, 0, 1372, 381, 1, 0, 0, 0, 1373, 1374, 3, 60, 22, 0, 1374, 1375, 1, 0, 0, 0, 1375, 1376, 6, 183, 11, 0, 1376, 383, 1, 0, 0, 0, 1377, 1378, 3, 62, 23, 0, 1378, 1379, 1, 0, 0, 0, 1379, 1380, 6, 184, 11, 0, 1380, 385, 1, 0, 0, 0, 1381, 1382, 3, 184, 84, 0, 1382, 1383, 1, 0, 0, 0, 1383, 1384, 6, 185, 15, 0, 1384, 1385, 6, 185, 0, 0, 1385, 1386, 6, 185, 25, 0, 1386, 387, 1, 0, 0, 0, 1387, 1388, 3, 180, 82, 0, 1388, 1389, 1, 0, 0, 0, 1389, 1390, 6, 186, 15, 0, 1390, 1391, 6, 186, 0, 0, 1391, 1392, 6, 186, 30, 0, 1392, 389, 1, 0, 0, 0, 1393, 1394, 3, 106, 45, 0, 1394, 1395, 1, 0, 0, 0, 1395, 1396, 6, 187, 15, 0, 1396, 1397, 6, 187, 0, 0, 1397, 1398, 6, 187, 32, 0, 1398, 391, 1, 0, 0, 0, 1399, 1400, 3, 78, 31, 0, 1400, 1401, 1, 0, 0, 0, 1401, 1402, 6, 188, 14, 0, 1402, 1403, 6, 188, 15, 0, 1403, 393, 1, 0, 0, 0, 62, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 566, 576, 580, 583, 592, 594, 605, 612, 617, 656, 661, 670, 677, 682, 684, 695, 703, 706, 708, 713, 718, 724, 731, 736, 742, 745, 753, 757, 890, 895, 900, 902, 908, 993, 997, 1002, 1007, 1012, 1014, 1018, 1020, 1097, 1101, 1106, 1324, 1326, 33, 5, 2, 0, 5, 4, 0, 5, 6, 0, 5, 1, 0, 5, 3, 0, 5, 8, 0, 5, 12, 0, 5, 14, 0, 5, 10, 0, 5, 5, 0, 5, 11, 0, 0, 1, 0, 7, 68, 0, 5, 0, 0, 7, 29, 0, 4, 0, 0, 7, 69, 0, 7, 38, 0, 7, 36, 0, 7, 30, 0, 7, 25, 0, 7, 40, 0, 7, 79, 0, 5, 13, 0, 5, 7, 0, 7, 71, 0, 7, 89, 0, 7, 88, 0, 7, 87, 0, 5, 9, 0, 7, 70, 0, 5, 15, 0, 7, 33, 0] \ No newline at end of file +[4, 0, 124, 1422, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 4, 20, 567, 8, 20, 11, 20, 12, 20, 568, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 5, 21, 577, 8, 21, 10, 21, 12, 21, 580, 9, 21, 1, 21, 3, 21, 583, 8, 21, 1, 21, 3, 21, 586, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 595, 8, 22, 10, 22, 12, 22, 598, 9, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 4, 23, 606, 8, 23, 11, 23, 12, 23, 607, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 3, 24, 615, 8, 24, 1, 25, 4, 25, 618, 8, 25, 11, 25, 12, 25, 619, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 3, 36, 659, 8, 36, 1, 36, 4, 36, 662, 8, 36, 11, 36, 12, 36, 663, 1, 37, 1, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 3, 39, 673, 8, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 3, 41, 680, 8, 41, 1, 42, 1, 42, 1, 42, 5, 42, 685, 8, 42, 10, 42, 12, 42, 688, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 5, 42, 696, 8, 42, 10, 42, 12, 42, 699, 9, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 3, 42, 706, 8, 42, 1, 42, 3, 42, 709, 8, 42, 3, 42, 711, 8, 42, 1, 43, 4, 43, 714, 8, 43, 11, 43, 12, 43, 715, 1, 44, 4, 44, 719, 8, 44, 11, 44, 12, 44, 720, 1, 44, 1, 44, 5, 44, 725, 8, 44, 10, 44, 12, 44, 728, 9, 44, 1, 44, 1, 44, 4, 44, 732, 8, 44, 11, 44, 12, 44, 733, 1, 44, 4, 44, 737, 8, 44, 11, 44, 12, 44, 738, 1, 44, 1, 44, 5, 44, 743, 8, 44, 10, 44, 12, 44, 746, 9, 44, 3, 44, 748, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 754, 8, 44, 11, 44, 12, 44, 755, 1, 44, 1, 44, 3, 44, 760, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 5, 80, 882, 8, 80, 10, 80, 12, 80, 885, 9, 80, 1, 80, 1, 80, 4, 80, 889, 8, 80, 11, 80, 12, 80, 890, 3, 80, 893, 8, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 5, 83, 907, 8, 83, 10, 83, 12, 83, 910, 9, 83, 1, 83, 1, 83, 3, 83, 914, 8, 83, 1, 83, 4, 83, 917, 8, 83, 11, 83, 12, 83, 918, 3, 83, 921, 8, 83, 1, 84, 1, 84, 4, 84, 925, 8, 84, 11, 84, 12, 84, 926, 1, 84, 1, 84, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 3, 103, 1012, 8, 103, 1, 104, 1, 104, 3, 104, 1016, 8, 104, 1, 104, 5, 104, 1019, 8, 104, 10, 104, 12, 104, 1022, 9, 104, 1, 104, 1, 104, 3, 104, 1026, 8, 104, 1, 104, 4, 104, 1029, 8, 104, 11, 104, 12, 104, 1030, 3, 104, 1033, 8, 104, 1, 105, 1, 105, 4, 105, 1037, 8, 105, 11, 105, 12, 105, 1038, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 123, 4, 123, 1114, 8, 123, 11, 123, 12, 123, 1115, 1, 123, 1, 123, 3, 123, 1120, 8, 123, 1, 123, 4, 123, 1123, 8, 123, 11, 123, 12, 123, 1124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 4, 173, 1343, 8, 173, 11, 173, 12, 173, 1344, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 2, 596, 697, 0, 190, 16, 1, 18, 2, 20, 3, 22, 4, 24, 5, 26, 6, 28, 7, 30, 8, 32, 9, 34, 10, 36, 11, 38, 12, 40, 13, 42, 14, 44, 15, 46, 16, 48, 17, 50, 18, 52, 19, 54, 20, 56, 21, 58, 22, 60, 23, 62, 24, 64, 0, 66, 25, 68, 0, 70, 0, 72, 26, 74, 27, 76, 28, 78, 29, 80, 0, 82, 0, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100, 30, 102, 31, 104, 32, 106, 33, 108, 34, 110, 35, 112, 36, 114, 37, 116, 38, 118, 39, 120, 40, 122, 41, 124, 42, 126, 43, 128, 44, 130, 45, 132, 46, 134, 47, 136, 48, 138, 49, 140, 50, 142, 51, 144, 52, 146, 53, 148, 54, 150, 55, 152, 56, 154, 57, 156, 58, 158, 59, 160, 60, 162, 61, 164, 62, 166, 63, 168, 64, 170, 65, 172, 66, 174, 67, 176, 68, 178, 69, 180, 70, 182, 71, 184, 0, 186, 72, 188, 73, 190, 74, 192, 75, 194, 0, 196, 0, 198, 0, 200, 0, 202, 0, 204, 0, 206, 76, 208, 0, 210, 77, 212, 78, 214, 79, 216, 0, 218, 0, 220, 0, 222, 0, 224, 0, 226, 80, 228, 81, 230, 82, 232, 83, 234, 0, 236, 0, 238, 0, 240, 0, 242, 84, 244, 0, 246, 85, 248, 86, 250, 87, 252, 0, 254, 0, 256, 88, 258, 89, 260, 0, 262, 90, 264, 0, 266, 0, 268, 91, 270, 92, 272, 93, 274, 0, 276, 0, 278, 0, 280, 0, 282, 0, 284, 0, 286, 0, 288, 94, 290, 95, 292, 96, 294, 0, 296, 0, 298, 0, 300, 0, 302, 0, 304, 97, 306, 98, 308, 99, 310, 0, 312, 0, 314, 0, 316, 0, 318, 100, 320, 101, 322, 102, 324, 0, 326, 0, 328, 0, 330, 0, 332, 103, 334, 104, 336, 105, 338, 0, 340, 106, 342, 107, 344, 108, 346, 109, 348, 0, 350, 110, 352, 111, 354, 112, 356, 113, 358, 0, 360, 114, 362, 115, 364, 116, 366, 117, 368, 118, 370, 0, 372, 0, 374, 119, 376, 120, 378, 121, 380, 0, 382, 122, 384, 123, 386, 124, 388, 0, 390, 0, 392, 0, 394, 0, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 35, 2, 0, 68, 68, 100, 100, 2, 0, 73, 73, 105, 105, 2, 0, 83, 83, 115, 115, 2, 0, 69, 69, 101, 101, 2, 0, 67, 67, 99, 99, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 78, 78, 110, 110, 2, 0, 72, 72, 104, 104, 2, 0, 86, 86, 118, 118, 2, 0, 65, 65, 97, 97, 2, 0, 76, 76, 108, 108, 2, 0, 88, 88, 120, 120, 2, 0, 70, 70, 102, 102, 2, 0, 77, 77, 109, 109, 2, 0, 71, 71, 103, 103, 2, 0, 75, 75, 107, 107, 2, 0, 85, 85, 117, 117, 2, 0, 87, 87, 119, 119, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 10, 0, 9, 10, 13, 13, 32, 32, 44, 44, 47, 47, 61, 61, 91, 91, 93, 93, 96, 96, 124, 124, 2, 0, 42, 42, 47, 47, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 78, 78, 82, 82, 84, 84, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 43, 43, 45, 45, 1, 0, 96, 96, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121, 121, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1448, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 1, 68, 1, 0, 0, 0, 1, 70, 1, 0, 0, 0, 1, 72, 1, 0, 0, 0, 1, 74, 1, 0, 0, 0, 1, 76, 1, 0, 0, 0, 2, 78, 1, 0, 0, 0, 2, 100, 1, 0, 0, 0, 2, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 112, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 2, 136, 1, 0, 0, 0, 2, 138, 1, 0, 0, 0, 2, 140, 1, 0, 0, 0, 2, 142, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 2, 146, 1, 0, 0, 0, 2, 148, 1, 0, 0, 0, 2, 150, 1, 0, 0, 0, 2, 152, 1, 0, 0, 0, 2, 154, 1, 0, 0, 0, 2, 156, 1, 0, 0, 0, 2, 158, 1, 0, 0, 0, 2, 160, 1, 0, 0, 0, 2, 162, 1, 0, 0, 0, 2, 164, 1, 0, 0, 0, 2, 166, 1, 0, 0, 0, 2, 168, 1, 0, 0, 0, 2, 170, 1, 0, 0, 0, 2, 172, 1, 0, 0, 0, 2, 174, 1, 0, 0, 0, 2, 176, 1, 0, 0, 0, 2, 178, 1, 0, 0, 0, 2, 180, 1, 0, 0, 0, 2, 182, 1, 0, 0, 0, 2, 186, 1, 0, 0, 0, 2, 188, 1, 0, 0, 0, 2, 190, 1, 0, 0, 0, 2, 192, 1, 0, 0, 0, 3, 194, 1, 0, 0, 0, 3, 196, 1, 0, 0, 0, 3, 198, 1, 0, 0, 0, 3, 200, 1, 0, 0, 0, 3, 202, 1, 0, 0, 0, 3, 204, 1, 0, 0, 0, 3, 206, 1, 0, 0, 0, 3, 208, 1, 0, 0, 0, 3, 210, 1, 0, 0, 0, 3, 212, 1, 0, 0, 0, 3, 214, 1, 0, 0, 0, 4, 216, 1, 0, 0, 0, 4, 218, 1, 0, 0, 0, 4, 220, 1, 0, 0, 0, 4, 226, 1, 0, 0, 0, 4, 228, 1, 0, 0, 0, 4, 230, 1, 0, 0, 0, 4, 232, 1, 0, 0, 0, 5, 234, 1, 0, 0, 0, 5, 236, 1, 0, 0, 0, 5, 238, 1, 0, 0, 0, 5, 240, 1, 0, 0, 0, 5, 242, 1, 0, 0, 0, 5, 244, 1, 0, 0, 0, 5, 246, 1, 0, 0, 0, 5, 248, 1, 0, 0, 0, 5, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 258, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 6, 264, 1, 0, 0, 0, 6, 266, 1, 0, 0, 0, 6, 268, 1, 0, 0, 0, 6, 270, 1, 0, 0, 0, 6, 272, 1, 0, 0, 0, 7, 274, 1, 0, 0, 0, 7, 276, 1, 0, 0, 0, 7, 278, 1, 0, 0, 0, 7, 280, 1, 0, 0, 0, 7, 282, 1, 0, 0, 0, 7, 284, 1, 0, 0, 0, 7, 286, 1, 0, 0, 0, 7, 288, 1, 0, 0, 0, 7, 290, 1, 0, 0, 0, 7, 292, 1, 0, 0, 0, 8, 294, 1, 0, 0, 0, 8, 296, 1, 0, 0, 0, 8, 298, 1, 0, 0, 0, 8, 300, 1, 0, 0, 0, 8, 302, 1, 0, 0, 0, 8, 304, 1, 0, 0, 0, 8, 306, 1, 0, 0, 0, 8, 308, 1, 0, 0, 0, 9, 310, 1, 0, 0, 0, 9, 312, 1, 0, 0, 0, 9, 314, 1, 0, 0, 0, 9, 316, 1, 0, 0, 0, 9, 318, 1, 0, 0, 0, 9, 320, 1, 0, 0, 0, 9, 322, 1, 0, 0, 0, 10, 324, 1, 0, 0, 0, 10, 326, 1, 0, 0, 0, 10, 328, 1, 0, 0, 0, 10, 330, 1, 0, 0, 0, 10, 332, 1, 0, 0, 0, 10, 334, 1, 0, 0, 0, 10, 336, 1, 0, 0, 0, 11, 338, 1, 0, 0, 0, 11, 340, 1, 0, 0, 0, 11, 342, 1, 0, 0, 0, 11, 344, 1, 0, 0, 0, 11, 346, 1, 0, 0, 0, 12, 348, 1, 0, 0, 0, 12, 350, 1, 0, 0, 0, 12, 352, 1, 0, 0, 0, 12, 354, 1, 0, 0, 0, 12, 356, 1, 0, 0, 0, 13, 358, 1, 0, 0, 0, 13, 360, 1, 0, 0, 0, 13, 362, 1, 0, 0, 0, 13, 364, 1, 0, 0, 0, 13, 366, 1, 0, 0, 0, 13, 368, 1, 0, 0, 0, 14, 370, 1, 0, 0, 0, 14, 372, 1, 0, 0, 0, 14, 374, 1, 0, 0, 0, 14, 376, 1, 0, 0, 0, 14, 378, 1, 0, 0, 0, 15, 380, 1, 0, 0, 0, 15, 382, 1, 0, 0, 0, 15, 384, 1, 0, 0, 0, 15, 386, 1, 0, 0, 0, 15, 388, 1, 0, 0, 0, 15, 390, 1, 0, 0, 0, 15, 392, 1, 0, 0, 0, 15, 394, 1, 0, 0, 0, 16, 396, 1, 0, 0, 0, 18, 406, 1, 0, 0, 0, 20, 413, 1, 0, 0, 0, 22, 422, 1, 0, 0, 0, 24, 429, 1, 0, 0, 0, 26, 439, 1, 0, 0, 0, 28, 446, 1, 0, 0, 0, 30, 453, 1, 0, 0, 0, 32, 467, 1, 0, 0, 0, 34, 474, 1, 0, 0, 0, 36, 482, 1, 0, 0, 0, 38, 491, 1, 0, 0, 0, 40, 498, 1, 0, 0, 0, 42, 508, 1, 0, 0, 0, 44, 520, 1, 0, 0, 0, 46, 529, 1, 0, 0, 0, 48, 535, 1, 0, 0, 0, 50, 542, 1, 0, 0, 0, 52, 549, 1, 0, 0, 0, 54, 557, 1, 0, 0, 0, 56, 566, 1, 0, 0, 0, 58, 572, 1, 0, 0, 0, 60, 589, 1, 0, 0, 0, 62, 605, 1, 0, 0, 0, 64, 614, 1, 0, 0, 0, 66, 617, 1, 0, 0, 0, 68, 621, 1, 0, 0, 0, 70, 626, 1, 0, 0, 0, 72, 631, 1, 0, 0, 0, 74, 635, 1, 0, 0, 0, 76, 639, 1, 0, 0, 0, 78, 643, 1, 0, 0, 0, 80, 647, 1, 0, 0, 0, 82, 649, 1, 0, 0, 0, 84, 651, 1, 0, 0, 0, 86, 654, 1, 0, 0, 0, 88, 656, 1, 0, 0, 0, 90, 665, 1, 0, 0, 0, 92, 667, 1, 0, 0, 0, 94, 672, 1, 0, 0, 0, 96, 674, 1, 0, 0, 0, 98, 679, 1, 0, 0, 0, 100, 710, 1, 0, 0, 0, 102, 713, 1, 0, 0, 0, 104, 759, 1, 0, 0, 0, 106, 761, 1, 0, 0, 0, 108, 764, 1, 0, 0, 0, 110, 768, 1, 0, 0, 0, 112, 772, 1, 0, 0, 0, 114, 774, 1, 0, 0, 0, 116, 777, 1, 0, 0, 0, 118, 779, 1, 0, 0, 0, 120, 784, 1, 0, 0, 0, 122, 786, 1, 0, 0, 0, 124, 792, 1, 0, 0, 0, 126, 798, 1, 0, 0, 0, 128, 803, 1, 0, 0, 0, 130, 805, 1, 0, 0, 0, 132, 808, 1, 0, 0, 0, 134, 811, 1, 0, 0, 0, 136, 816, 1, 0, 0, 0, 138, 820, 1, 0, 0, 0, 140, 825, 1, 0, 0, 0, 142, 831, 1, 0, 0, 0, 144, 834, 1, 0, 0, 0, 146, 836, 1, 0, 0, 0, 148, 842, 1, 0, 0, 0, 150, 844, 1, 0, 0, 0, 152, 849, 1, 0, 0, 0, 154, 852, 1, 0, 0, 0, 156, 855, 1, 0, 0, 0, 158, 858, 1, 0, 0, 0, 160, 860, 1, 0, 0, 0, 162, 863, 1, 0, 0, 0, 164, 865, 1, 0, 0, 0, 166, 868, 1, 0, 0, 0, 168, 870, 1, 0, 0, 0, 170, 872, 1, 0, 0, 0, 172, 874, 1, 0, 0, 0, 174, 876, 1, 0, 0, 0, 176, 892, 1, 0, 0, 0, 178, 894, 1, 0, 0, 0, 180, 899, 1, 0, 0, 0, 182, 920, 1, 0, 0, 0, 184, 922, 1, 0, 0, 0, 186, 930, 1, 0, 0, 0, 188, 932, 1, 0, 0, 0, 190, 936, 1, 0, 0, 0, 192, 940, 1, 0, 0, 0, 194, 944, 1, 0, 0, 0, 196, 949, 1, 0, 0, 0, 198, 953, 1, 0, 0, 0, 200, 957, 1, 0, 0, 0, 202, 961, 1, 0, 0, 0, 204, 965, 1, 0, 0, 0, 206, 969, 1, 0, 0, 0, 208, 978, 1, 0, 0, 0, 210, 982, 1, 0, 0, 0, 212, 986, 1, 0, 0, 0, 214, 990, 1, 0, 0, 0, 216, 994, 1, 0, 0, 0, 218, 999, 1, 0, 0, 0, 220, 1003, 1, 0, 0, 0, 222, 1011, 1, 0, 0, 0, 224, 1032, 1, 0, 0, 0, 226, 1036, 1, 0, 0, 0, 228, 1040, 1, 0, 0, 0, 230, 1044, 1, 0, 0, 0, 232, 1048, 1, 0, 0, 0, 234, 1052, 1, 0, 0, 0, 236, 1057, 1, 0, 0, 0, 238, 1061, 1, 0, 0, 0, 240, 1065, 1, 0, 0, 0, 242, 1069, 1, 0, 0, 0, 244, 1072, 1, 0, 0, 0, 246, 1076, 1, 0, 0, 0, 248, 1080, 1, 0, 0, 0, 250, 1084, 1, 0, 0, 0, 252, 1088, 1, 0, 0, 0, 254, 1093, 1, 0, 0, 0, 256, 1098, 1, 0, 0, 0, 258, 1103, 1, 0, 0, 0, 260, 1110, 1, 0, 0, 0, 262, 1119, 1, 0, 0, 0, 264, 1126, 1, 0, 0, 0, 266, 1130, 1, 0, 0, 0, 268, 1134, 1, 0, 0, 0, 270, 1138, 1, 0, 0, 0, 272, 1142, 1, 0, 0, 0, 274, 1146, 1, 0, 0, 0, 276, 1152, 1, 0, 0, 0, 278, 1156, 1, 0, 0, 0, 280, 1160, 1, 0, 0, 0, 282, 1164, 1, 0, 0, 0, 284, 1168, 1, 0, 0, 0, 286, 1172, 1, 0, 0, 0, 288, 1176, 1, 0, 0, 0, 290, 1180, 1, 0, 0, 0, 292, 1184, 1, 0, 0, 0, 294, 1188, 1, 0, 0, 0, 296, 1193, 1, 0, 0, 0, 298, 1197, 1, 0, 0, 0, 300, 1201, 1, 0, 0, 0, 302, 1206, 1, 0, 0, 0, 304, 1210, 1, 0, 0, 0, 306, 1214, 1, 0, 0, 0, 308, 1218, 1, 0, 0, 0, 310, 1222, 1, 0, 0, 0, 312, 1228, 1, 0, 0, 0, 314, 1232, 1, 0, 0, 0, 316, 1236, 1, 0, 0, 0, 318, 1240, 1, 0, 0, 0, 320, 1244, 1, 0, 0, 0, 322, 1248, 1, 0, 0, 0, 324, 1252, 1, 0, 0, 0, 326, 1257, 1, 0, 0, 0, 328, 1261, 1, 0, 0, 0, 330, 1265, 1, 0, 0, 0, 332, 1269, 1, 0, 0, 0, 334, 1273, 1, 0, 0, 0, 336, 1277, 1, 0, 0, 0, 338, 1281, 1, 0, 0, 0, 340, 1286, 1, 0, 0, 0, 342, 1291, 1, 0, 0, 0, 344, 1295, 1, 0, 0, 0, 346, 1299, 1, 0, 0, 0, 348, 1303, 1, 0, 0, 0, 350, 1308, 1, 0, 0, 0, 352, 1318, 1, 0, 0, 0, 354, 1322, 1, 0, 0, 0, 356, 1326, 1, 0, 0, 0, 358, 1330, 1, 0, 0, 0, 360, 1335, 1, 0, 0, 0, 362, 1342, 1, 0, 0, 0, 364, 1346, 1, 0, 0, 0, 366, 1350, 1, 0, 0, 0, 368, 1354, 1, 0, 0, 0, 370, 1358, 1, 0, 0, 0, 372, 1363, 1, 0, 0, 0, 374, 1369, 1, 0, 0, 0, 376, 1373, 1, 0, 0, 0, 378, 1377, 1, 0, 0, 0, 380, 1381, 1, 0, 0, 0, 382, 1387, 1, 0, 0, 0, 384, 1391, 1, 0, 0, 0, 386, 1395, 1, 0, 0, 0, 388, 1399, 1, 0, 0, 0, 390, 1405, 1, 0, 0, 0, 392, 1411, 1, 0, 0, 0, 394, 1417, 1, 0, 0, 0, 396, 397, 7, 0, 0, 0, 397, 398, 7, 1, 0, 0, 398, 399, 7, 2, 0, 0, 399, 400, 7, 2, 0, 0, 400, 401, 7, 3, 0, 0, 401, 402, 7, 4, 0, 0, 402, 403, 7, 5, 0, 0, 403, 404, 1, 0, 0, 0, 404, 405, 6, 0, 0, 0, 405, 17, 1, 0, 0, 0, 406, 407, 7, 0, 0, 0, 407, 408, 7, 6, 0, 0, 408, 409, 7, 7, 0, 0, 409, 410, 7, 8, 0, 0, 410, 411, 1, 0, 0, 0, 411, 412, 6, 1, 1, 0, 412, 19, 1, 0, 0, 0, 413, 414, 7, 3, 0, 0, 414, 415, 7, 9, 0, 0, 415, 416, 7, 6, 0, 0, 416, 417, 7, 1, 0, 0, 417, 418, 7, 4, 0, 0, 418, 419, 7, 10, 0, 0, 419, 420, 1, 0, 0, 0, 420, 421, 6, 2, 2, 0, 421, 21, 1, 0, 0, 0, 422, 423, 7, 3, 0, 0, 423, 424, 7, 11, 0, 0, 424, 425, 7, 12, 0, 0, 425, 426, 7, 13, 0, 0, 426, 427, 1, 0, 0, 0, 427, 428, 6, 3, 0, 0, 428, 23, 1, 0, 0, 0, 429, 430, 7, 3, 0, 0, 430, 431, 7, 14, 0, 0, 431, 432, 7, 8, 0, 0, 432, 433, 7, 13, 0, 0, 433, 434, 7, 12, 0, 0, 434, 435, 7, 1, 0, 0, 435, 436, 7, 9, 0, 0, 436, 437, 1, 0, 0, 0, 437, 438, 6, 4, 3, 0, 438, 25, 1, 0, 0, 0, 439, 440, 7, 15, 0, 0, 440, 441, 7, 6, 0, 0, 441, 442, 7, 7, 0, 0, 442, 443, 7, 16, 0, 0, 443, 444, 1, 0, 0, 0, 444, 445, 6, 5, 4, 0, 445, 27, 1, 0, 0, 0, 446, 447, 7, 17, 0, 0, 447, 448, 7, 6, 0, 0, 448, 449, 7, 7, 0, 0, 449, 450, 7, 18, 0, 0, 450, 451, 1, 0, 0, 0, 451, 452, 6, 6, 0, 0, 452, 29, 1, 0, 0, 0, 453, 454, 7, 1, 0, 0, 454, 455, 7, 9, 0, 0, 455, 456, 7, 13, 0, 0, 456, 457, 7, 1, 0, 0, 457, 458, 7, 9, 0, 0, 458, 459, 7, 3, 0, 0, 459, 460, 7, 2, 0, 0, 460, 461, 7, 5, 0, 0, 461, 462, 7, 12, 0, 0, 462, 463, 7, 5, 0, 0, 463, 464, 7, 2, 0, 0, 464, 465, 1, 0, 0, 0, 465, 466, 6, 7, 0, 0, 466, 31, 1, 0, 0, 0, 467, 468, 7, 18, 0, 0, 468, 469, 7, 3, 0, 0, 469, 470, 7, 3, 0, 0, 470, 471, 7, 8, 0, 0, 471, 472, 1, 0, 0, 0, 472, 473, 6, 8, 1, 0, 473, 33, 1, 0, 0, 0, 474, 475, 7, 13, 0, 0, 475, 476, 7, 1, 0, 0, 476, 477, 7, 16, 0, 0, 477, 478, 7, 1, 0, 0, 478, 479, 7, 5, 0, 0, 479, 480, 1, 0, 0, 0, 480, 481, 6, 9, 0, 0, 481, 35, 1, 0, 0, 0, 482, 483, 7, 13, 0, 0, 483, 484, 7, 7, 0, 0, 484, 485, 7, 7, 0, 0, 485, 486, 7, 18, 0, 0, 486, 487, 7, 19, 0, 0, 487, 488, 7, 8, 0, 0, 488, 489, 1, 0, 0, 0, 489, 490, 6, 10, 5, 0, 490, 37, 1, 0, 0, 0, 491, 492, 7, 16, 0, 0, 492, 493, 7, 3, 0, 0, 493, 494, 7, 5, 0, 0, 494, 495, 7, 12, 0, 0, 495, 496, 1, 0, 0, 0, 496, 497, 6, 11, 6, 0, 497, 39, 1, 0, 0, 0, 498, 499, 7, 16, 0, 0, 499, 500, 7, 3, 0, 0, 500, 501, 7, 5, 0, 0, 501, 502, 7, 6, 0, 0, 502, 503, 7, 1, 0, 0, 503, 504, 7, 4, 0, 0, 504, 505, 7, 2, 0, 0, 505, 506, 1, 0, 0, 0, 506, 507, 6, 12, 7, 0, 507, 41, 1, 0, 0, 0, 508, 509, 7, 16, 0, 0, 509, 510, 7, 11, 0, 0, 510, 511, 5, 95, 0, 0, 511, 512, 7, 3, 0, 0, 512, 513, 7, 14, 0, 0, 513, 514, 7, 8, 0, 0, 514, 515, 7, 12, 0, 0, 515, 516, 7, 9, 0, 0, 516, 517, 7, 0, 0, 0, 517, 518, 1, 0, 0, 0, 518, 519, 6, 13, 8, 0, 519, 43, 1, 0, 0, 0, 520, 521, 7, 6, 0, 0, 521, 522, 7, 3, 0, 0, 522, 523, 7, 9, 0, 0, 523, 524, 7, 12, 0, 0, 524, 525, 7, 16, 0, 0, 525, 526, 7, 3, 0, 0, 526, 527, 1, 0, 0, 0, 527, 528, 6, 14, 9, 0, 528, 45, 1, 0, 0, 0, 529, 530, 7, 6, 0, 0, 530, 531, 7, 7, 0, 0, 531, 532, 7, 20, 0, 0, 532, 533, 1, 0, 0, 0, 533, 534, 6, 15, 0, 0, 534, 47, 1, 0, 0, 0, 535, 536, 7, 2, 0, 0, 536, 537, 7, 10, 0, 0, 537, 538, 7, 7, 0, 0, 538, 539, 7, 20, 0, 0, 539, 540, 1, 0, 0, 0, 540, 541, 6, 16, 10, 0, 541, 49, 1, 0, 0, 0, 542, 543, 7, 2, 0, 0, 543, 544, 7, 7, 0, 0, 544, 545, 7, 6, 0, 0, 545, 546, 7, 5, 0, 0, 546, 547, 1, 0, 0, 0, 547, 548, 6, 17, 0, 0, 548, 51, 1, 0, 0, 0, 549, 550, 7, 2, 0, 0, 550, 551, 7, 5, 0, 0, 551, 552, 7, 12, 0, 0, 552, 553, 7, 5, 0, 0, 553, 554, 7, 2, 0, 0, 554, 555, 1, 0, 0, 0, 555, 556, 6, 18, 0, 0, 556, 53, 1, 0, 0, 0, 557, 558, 7, 20, 0, 0, 558, 559, 7, 10, 0, 0, 559, 560, 7, 3, 0, 0, 560, 561, 7, 6, 0, 0, 561, 562, 7, 3, 0, 0, 562, 563, 1, 0, 0, 0, 563, 564, 6, 19, 0, 0, 564, 55, 1, 0, 0, 0, 565, 567, 8, 21, 0, 0, 566, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 566, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 570, 1, 0, 0, 0, 570, 571, 6, 20, 0, 0, 571, 57, 1, 0, 0, 0, 572, 573, 5, 47, 0, 0, 573, 574, 5, 47, 0, 0, 574, 578, 1, 0, 0, 0, 575, 577, 8, 22, 0, 0, 576, 575, 1, 0, 0, 0, 577, 580, 1, 0, 0, 0, 578, 576, 1, 0, 0, 0, 578, 579, 1, 0, 0, 0, 579, 582, 1, 0, 0, 0, 580, 578, 1, 0, 0, 0, 581, 583, 5, 13, 0, 0, 582, 581, 1, 0, 0, 0, 582, 583, 1, 0, 0, 0, 583, 585, 1, 0, 0, 0, 584, 586, 5, 10, 0, 0, 585, 584, 1, 0, 0, 0, 585, 586, 1, 0, 0, 0, 586, 587, 1, 0, 0, 0, 587, 588, 6, 21, 11, 0, 588, 59, 1, 0, 0, 0, 589, 590, 5, 47, 0, 0, 590, 591, 5, 42, 0, 0, 591, 596, 1, 0, 0, 0, 592, 595, 3, 60, 22, 0, 593, 595, 9, 0, 0, 0, 594, 592, 1, 0, 0, 0, 594, 593, 1, 0, 0, 0, 595, 598, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 596, 594, 1, 0, 0, 0, 597, 599, 1, 0, 0, 0, 598, 596, 1, 0, 0, 0, 599, 600, 5, 42, 0, 0, 600, 601, 5, 47, 0, 0, 601, 602, 1, 0, 0, 0, 602, 603, 6, 22, 11, 0, 603, 61, 1, 0, 0, 0, 604, 606, 7, 23, 0, 0, 605, 604, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 605, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 1, 0, 0, 0, 609, 610, 6, 23, 11, 0, 610, 63, 1, 0, 0, 0, 611, 615, 8, 24, 0, 0, 612, 613, 5, 47, 0, 0, 613, 615, 8, 25, 0, 0, 614, 611, 1, 0, 0, 0, 614, 612, 1, 0, 0, 0, 615, 65, 1, 0, 0, 0, 616, 618, 3, 64, 24, 0, 617, 616, 1, 0, 0, 0, 618, 619, 1, 0, 0, 0, 619, 617, 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 67, 1, 0, 0, 0, 621, 622, 3, 178, 81, 0, 622, 623, 1, 0, 0, 0, 623, 624, 6, 26, 12, 0, 624, 625, 6, 26, 13, 0, 625, 69, 1, 0, 0, 0, 626, 627, 3, 78, 31, 0, 627, 628, 1, 0, 0, 0, 628, 629, 6, 27, 14, 0, 629, 630, 6, 27, 15, 0, 630, 71, 1, 0, 0, 0, 631, 632, 3, 62, 23, 0, 632, 633, 1, 0, 0, 0, 633, 634, 6, 28, 11, 0, 634, 73, 1, 0, 0, 0, 635, 636, 3, 58, 21, 0, 636, 637, 1, 0, 0, 0, 637, 638, 6, 29, 11, 0, 638, 75, 1, 0, 0, 0, 639, 640, 3, 60, 22, 0, 640, 641, 1, 0, 0, 0, 641, 642, 6, 30, 11, 0, 642, 77, 1, 0, 0, 0, 643, 644, 5, 124, 0, 0, 644, 645, 1, 0, 0, 0, 645, 646, 6, 31, 15, 0, 646, 79, 1, 0, 0, 0, 647, 648, 7, 26, 0, 0, 648, 81, 1, 0, 0, 0, 649, 650, 7, 27, 0, 0, 650, 83, 1, 0, 0, 0, 651, 652, 5, 92, 0, 0, 652, 653, 7, 28, 0, 0, 653, 85, 1, 0, 0, 0, 654, 655, 8, 29, 0, 0, 655, 87, 1, 0, 0, 0, 656, 658, 7, 3, 0, 0, 657, 659, 7, 30, 0, 0, 658, 657, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 661, 1, 0, 0, 0, 660, 662, 3, 80, 32, 0, 661, 660, 1, 0, 0, 0, 662, 663, 1, 0, 0, 0, 663, 661, 1, 0, 0, 0, 663, 664, 1, 0, 0, 0, 664, 89, 1, 0, 0, 0, 665, 666, 5, 64, 0, 0, 666, 91, 1, 0, 0, 0, 667, 668, 5, 96, 0, 0, 668, 93, 1, 0, 0, 0, 669, 673, 8, 31, 0, 0, 670, 671, 5, 96, 0, 0, 671, 673, 5, 96, 0, 0, 672, 669, 1, 0, 0, 0, 672, 670, 1, 0, 0, 0, 673, 95, 1, 0, 0, 0, 674, 675, 5, 95, 0, 0, 675, 97, 1, 0, 0, 0, 676, 680, 3, 82, 33, 0, 677, 680, 3, 80, 32, 0, 678, 680, 3, 96, 40, 0, 679, 676, 1, 0, 0, 0, 679, 677, 1, 0, 0, 0, 679, 678, 1, 0, 0, 0, 680, 99, 1, 0, 0, 0, 681, 686, 5, 34, 0, 0, 682, 685, 3, 84, 34, 0, 683, 685, 3, 86, 35, 0, 684, 682, 1, 0, 0, 0, 684, 683, 1, 0, 0, 0, 685, 688, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 686, 687, 1, 0, 0, 0, 687, 689, 1, 0, 0, 0, 688, 686, 1, 0, 0, 0, 689, 711, 5, 34, 0, 0, 690, 691, 5, 34, 0, 0, 691, 692, 5, 34, 0, 0, 692, 693, 5, 34, 0, 0, 693, 697, 1, 0, 0, 0, 694, 696, 8, 22, 0, 0, 695, 694, 1, 0, 0, 0, 696, 699, 1, 0, 0, 0, 697, 698, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 698, 700, 1, 0, 0, 0, 699, 697, 1, 0, 0, 0, 700, 701, 5, 34, 0, 0, 701, 702, 5, 34, 0, 0, 702, 703, 5, 34, 0, 0, 703, 705, 1, 0, 0, 0, 704, 706, 5, 34, 0, 0, 705, 704, 1, 0, 0, 0, 705, 706, 1, 0, 0, 0, 706, 708, 1, 0, 0, 0, 707, 709, 5, 34, 0, 0, 708, 707, 1, 0, 0, 0, 708, 709, 1, 0, 0, 0, 709, 711, 1, 0, 0, 0, 710, 681, 1, 0, 0, 0, 710, 690, 1, 0, 0, 0, 711, 101, 1, 0, 0, 0, 712, 714, 3, 80, 32, 0, 713, 712, 1, 0, 0, 0, 714, 715, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 103, 1, 0, 0, 0, 717, 719, 3, 80, 32, 0, 718, 717, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 718, 1, 0, 0, 0, 720, 721, 1, 0, 0, 0, 721, 722, 1, 0, 0, 0, 722, 726, 3, 120, 52, 0, 723, 725, 3, 80, 32, 0, 724, 723, 1, 0, 0, 0, 725, 728, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 760, 1, 0, 0, 0, 728, 726, 1, 0, 0, 0, 729, 731, 3, 120, 52, 0, 730, 732, 3, 80, 32, 0, 731, 730, 1, 0, 0, 0, 732, 733, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 733, 734, 1, 0, 0, 0, 734, 760, 1, 0, 0, 0, 735, 737, 3, 80, 32, 0, 736, 735, 1, 0, 0, 0, 737, 738, 1, 0, 0, 0, 738, 736, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 747, 1, 0, 0, 0, 740, 744, 3, 120, 52, 0, 741, 743, 3, 80, 32, 0, 742, 741, 1, 0, 0, 0, 743, 746, 1, 0, 0, 0, 744, 742, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 748, 1, 0, 0, 0, 746, 744, 1, 0, 0, 0, 747, 740, 1, 0, 0, 0, 747, 748, 1, 0, 0, 0, 748, 749, 1, 0, 0, 0, 749, 750, 3, 88, 36, 0, 750, 760, 1, 0, 0, 0, 751, 753, 3, 120, 52, 0, 752, 754, 3, 80, 32, 0, 753, 752, 1, 0, 0, 0, 754, 755, 1, 0, 0, 0, 755, 753, 1, 0, 0, 0, 755, 756, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, 757, 758, 3, 88, 36, 0, 758, 760, 1, 0, 0, 0, 759, 718, 1, 0, 0, 0, 759, 729, 1, 0, 0, 0, 759, 736, 1, 0, 0, 0, 759, 751, 1, 0, 0, 0, 760, 105, 1, 0, 0, 0, 761, 762, 7, 32, 0, 0, 762, 763, 7, 33, 0, 0, 763, 107, 1, 0, 0, 0, 764, 765, 7, 12, 0, 0, 765, 766, 7, 9, 0, 0, 766, 767, 7, 0, 0, 0, 767, 109, 1, 0, 0, 0, 768, 769, 7, 12, 0, 0, 769, 770, 7, 2, 0, 0, 770, 771, 7, 4, 0, 0, 771, 111, 1, 0, 0, 0, 772, 773, 5, 61, 0, 0, 773, 113, 1, 0, 0, 0, 774, 775, 5, 58, 0, 0, 775, 776, 5, 58, 0, 0, 776, 115, 1, 0, 0, 0, 777, 778, 5, 44, 0, 0, 778, 117, 1, 0, 0, 0, 779, 780, 7, 0, 0, 0, 780, 781, 7, 3, 0, 0, 781, 782, 7, 2, 0, 0, 782, 783, 7, 4, 0, 0, 783, 119, 1, 0, 0, 0, 784, 785, 5, 46, 0, 0, 785, 121, 1, 0, 0, 0, 786, 787, 7, 15, 0, 0, 787, 788, 7, 12, 0, 0, 788, 789, 7, 13, 0, 0, 789, 790, 7, 2, 0, 0, 790, 791, 7, 3, 0, 0, 791, 123, 1, 0, 0, 0, 792, 793, 7, 15, 0, 0, 793, 794, 7, 1, 0, 0, 794, 795, 7, 6, 0, 0, 795, 796, 7, 2, 0, 0, 796, 797, 7, 5, 0, 0, 797, 125, 1, 0, 0, 0, 798, 799, 7, 13, 0, 0, 799, 800, 7, 12, 0, 0, 800, 801, 7, 2, 0, 0, 801, 802, 7, 5, 0, 0, 802, 127, 1, 0, 0, 0, 803, 804, 5, 40, 0, 0, 804, 129, 1, 0, 0, 0, 805, 806, 7, 1, 0, 0, 806, 807, 7, 9, 0, 0, 807, 131, 1, 0, 0, 0, 808, 809, 7, 1, 0, 0, 809, 810, 7, 2, 0, 0, 810, 133, 1, 0, 0, 0, 811, 812, 7, 13, 0, 0, 812, 813, 7, 1, 0, 0, 813, 814, 7, 18, 0, 0, 814, 815, 7, 3, 0, 0, 815, 135, 1, 0, 0, 0, 816, 817, 7, 9, 0, 0, 817, 818, 7, 7, 0, 0, 818, 819, 7, 5, 0, 0, 819, 137, 1, 0, 0, 0, 820, 821, 7, 9, 0, 0, 821, 822, 7, 19, 0, 0, 822, 823, 7, 13, 0, 0, 823, 824, 7, 13, 0, 0, 824, 139, 1, 0, 0, 0, 825, 826, 7, 9, 0, 0, 826, 827, 7, 19, 0, 0, 827, 828, 7, 13, 0, 0, 828, 829, 7, 13, 0, 0, 829, 830, 7, 2, 0, 0, 830, 141, 1, 0, 0, 0, 831, 832, 7, 7, 0, 0, 832, 833, 7, 6, 0, 0, 833, 143, 1, 0, 0, 0, 834, 835, 5, 63, 0, 0, 835, 145, 1, 0, 0, 0, 836, 837, 7, 6, 0, 0, 837, 838, 7, 13, 0, 0, 838, 839, 7, 1, 0, 0, 839, 840, 7, 18, 0, 0, 840, 841, 7, 3, 0, 0, 841, 147, 1, 0, 0, 0, 842, 843, 5, 41, 0, 0, 843, 149, 1, 0, 0, 0, 844, 845, 7, 5, 0, 0, 845, 846, 7, 6, 0, 0, 846, 847, 7, 19, 0, 0, 847, 848, 7, 3, 0, 0, 848, 151, 1, 0, 0, 0, 849, 850, 5, 61, 0, 0, 850, 851, 5, 61, 0, 0, 851, 153, 1, 0, 0, 0, 852, 853, 5, 61, 0, 0, 853, 854, 5, 126, 0, 0, 854, 155, 1, 0, 0, 0, 855, 856, 5, 33, 0, 0, 856, 857, 5, 61, 0, 0, 857, 157, 1, 0, 0, 0, 858, 859, 5, 60, 0, 0, 859, 159, 1, 0, 0, 0, 860, 861, 5, 60, 0, 0, 861, 862, 5, 61, 0, 0, 862, 161, 1, 0, 0, 0, 863, 864, 5, 62, 0, 0, 864, 163, 1, 0, 0, 0, 865, 866, 5, 62, 0, 0, 866, 867, 5, 61, 0, 0, 867, 165, 1, 0, 0, 0, 868, 869, 5, 43, 0, 0, 869, 167, 1, 0, 0, 0, 870, 871, 5, 45, 0, 0, 871, 169, 1, 0, 0, 0, 872, 873, 5, 42, 0, 0, 873, 171, 1, 0, 0, 0, 874, 875, 5, 47, 0, 0, 875, 173, 1, 0, 0, 0, 876, 877, 5, 37, 0, 0, 877, 175, 1, 0, 0, 0, 878, 879, 3, 144, 64, 0, 879, 883, 3, 82, 33, 0, 880, 882, 3, 98, 41, 0, 881, 880, 1, 0, 0, 0, 882, 885, 1, 0, 0, 0, 883, 881, 1, 0, 0, 0, 883, 884, 1, 0, 0, 0, 884, 893, 1, 0, 0, 0, 885, 883, 1, 0, 0, 0, 886, 888, 3, 144, 64, 0, 887, 889, 3, 80, 32, 0, 888, 887, 1, 0, 0, 0, 889, 890, 1, 0, 0, 0, 890, 888, 1, 0, 0, 0, 890, 891, 1, 0, 0, 0, 891, 893, 1, 0, 0, 0, 892, 878, 1, 0, 0, 0, 892, 886, 1, 0, 0, 0, 893, 177, 1, 0, 0, 0, 894, 895, 5, 91, 0, 0, 895, 896, 1, 0, 0, 0, 896, 897, 6, 81, 0, 0, 897, 898, 6, 81, 0, 0, 898, 179, 1, 0, 0, 0, 899, 900, 5, 93, 0, 0, 900, 901, 1, 0, 0, 0, 901, 902, 6, 82, 15, 0, 902, 903, 6, 82, 15, 0, 903, 181, 1, 0, 0, 0, 904, 908, 3, 82, 33, 0, 905, 907, 3, 98, 41, 0, 906, 905, 1, 0, 0, 0, 907, 910, 1, 0, 0, 0, 908, 906, 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 921, 1, 0, 0, 0, 910, 908, 1, 0, 0, 0, 911, 914, 3, 96, 40, 0, 912, 914, 3, 90, 37, 0, 913, 911, 1, 0, 0, 0, 913, 912, 1, 0, 0, 0, 914, 916, 1, 0, 0, 0, 915, 917, 3, 98, 41, 0, 916, 915, 1, 0, 0, 0, 917, 918, 1, 0, 0, 0, 918, 916, 1, 0, 0, 0, 918, 919, 1, 0, 0, 0, 919, 921, 1, 0, 0, 0, 920, 904, 1, 0, 0, 0, 920, 913, 1, 0, 0, 0, 921, 183, 1, 0, 0, 0, 922, 924, 3, 92, 38, 0, 923, 925, 3, 94, 39, 0, 924, 923, 1, 0, 0, 0, 925, 926, 1, 0, 0, 0, 926, 924, 1, 0, 0, 0, 926, 927, 1, 0, 0, 0, 927, 928, 1, 0, 0, 0, 928, 929, 3, 92, 38, 0, 929, 185, 1, 0, 0, 0, 930, 931, 3, 184, 84, 0, 931, 187, 1, 0, 0, 0, 932, 933, 3, 58, 21, 0, 933, 934, 1, 0, 0, 0, 934, 935, 6, 86, 11, 0, 935, 189, 1, 0, 0, 0, 936, 937, 3, 60, 22, 0, 937, 938, 1, 0, 0, 0, 938, 939, 6, 87, 11, 0, 939, 191, 1, 0, 0, 0, 940, 941, 3, 62, 23, 0, 941, 942, 1, 0, 0, 0, 942, 943, 6, 88, 11, 0, 943, 193, 1, 0, 0, 0, 944, 945, 3, 78, 31, 0, 945, 946, 1, 0, 0, 0, 946, 947, 6, 89, 14, 0, 947, 948, 6, 89, 15, 0, 948, 195, 1, 0, 0, 0, 949, 950, 3, 178, 81, 0, 950, 951, 1, 0, 0, 0, 951, 952, 6, 90, 12, 0, 952, 197, 1, 0, 0, 0, 953, 954, 3, 180, 82, 0, 954, 955, 1, 0, 0, 0, 955, 956, 6, 91, 16, 0, 956, 199, 1, 0, 0, 0, 957, 958, 3, 116, 50, 0, 958, 959, 1, 0, 0, 0, 959, 960, 6, 92, 17, 0, 960, 201, 1, 0, 0, 0, 961, 962, 3, 112, 48, 0, 962, 963, 1, 0, 0, 0, 963, 964, 6, 93, 18, 0, 964, 203, 1, 0, 0, 0, 965, 966, 3, 100, 42, 0, 966, 967, 1, 0, 0, 0, 967, 968, 6, 94, 19, 0, 968, 205, 1, 0, 0, 0, 969, 970, 7, 16, 0, 0, 970, 971, 7, 3, 0, 0, 971, 972, 7, 5, 0, 0, 972, 973, 7, 12, 0, 0, 973, 974, 7, 0, 0, 0, 974, 975, 7, 12, 0, 0, 975, 976, 7, 5, 0, 0, 976, 977, 7, 12, 0, 0, 977, 207, 1, 0, 0, 0, 978, 979, 3, 66, 25, 0, 979, 980, 1, 0, 0, 0, 980, 981, 6, 96, 20, 0, 981, 209, 1, 0, 0, 0, 982, 983, 3, 58, 21, 0, 983, 984, 1, 0, 0, 0, 984, 985, 6, 97, 11, 0, 985, 211, 1, 0, 0, 0, 986, 987, 3, 60, 22, 0, 987, 988, 1, 0, 0, 0, 988, 989, 6, 98, 11, 0, 989, 213, 1, 0, 0, 0, 990, 991, 3, 62, 23, 0, 991, 992, 1, 0, 0, 0, 992, 993, 6, 99, 11, 0, 993, 215, 1, 0, 0, 0, 994, 995, 3, 78, 31, 0, 995, 996, 1, 0, 0, 0, 996, 997, 6, 100, 14, 0, 997, 998, 6, 100, 15, 0, 998, 217, 1, 0, 0, 0, 999, 1000, 3, 120, 52, 0, 1000, 1001, 1, 0, 0, 0, 1001, 1002, 6, 101, 21, 0, 1002, 219, 1, 0, 0, 0, 1003, 1004, 3, 116, 50, 0, 1004, 1005, 1, 0, 0, 0, 1005, 1006, 6, 102, 17, 0, 1006, 221, 1, 0, 0, 0, 1007, 1012, 3, 82, 33, 0, 1008, 1012, 3, 80, 32, 0, 1009, 1012, 3, 96, 40, 0, 1010, 1012, 3, 170, 77, 0, 1011, 1007, 1, 0, 0, 0, 1011, 1008, 1, 0, 0, 0, 1011, 1009, 1, 0, 0, 0, 1011, 1010, 1, 0, 0, 0, 1012, 223, 1, 0, 0, 0, 1013, 1016, 3, 82, 33, 0, 1014, 1016, 3, 170, 77, 0, 1015, 1013, 1, 0, 0, 0, 1015, 1014, 1, 0, 0, 0, 1016, 1020, 1, 0, 0, 0, 1017, 1019, 3, 222, 103, 0, 1018, 1017, 1, 0, 0, 0, 1019, 1022, 1, 0, 0, 0, 1020, 1018, 1, 0, 0, 0, 1020, 1021, 1, 0, 0, 0, 1021, 1033, 1, 0, 0, 0, 1022, 1020, 1, 0, 0, 0, 1023, 1026, 3, 96, 40, 0, 1024, 1026, 3, 90, 37, 0, 1025, 1023, 1, 0, 0, 0, 1025, 1024, 1, 0, 0, 0, 1026, 1028, 1, 0, 0, 0, 1027, 1029, 3, 222, 103, 0, 1028, 1027, 1, 0, 0, 0, 1029, 1030, 1, 0, 0, 0, 1030, 1028, 1, 0, 0, 0, 1030, 1031, 1, 0, 0, 0, 1031, 1033, 1, 0, 0, 0, 1032, 1015, 1, 0, 0, 0, 1032, 1025, 1, 0, 0, 0, 1033, 225, 1, 0, 0, 0, 1034, 1037, 3, 224, 104, 0, 1035, 1037, 3, 184, 84, 0, 1036, 1034, 1, 0, 0, 0, 1036, 1035, 1, 0, 0, 0, 1037, 1038, 1, 0, 0, 0, 1038, 1036, 1, 0, 0, 0, 1038, 1039, 1, 0, 0, 0, 1039, 227, 1, 0, 0, 0, 1040, 1041, 3, 58, 21, 0, 1041, 1042, 1, 0, 0, 0, 1042, 1043, 6, 106, 11, 0, 1043, 229, 1, 0, 0, 0, 1044, 1045, 3, 60, 22, 0, 1045, 1046, 1, 0, 0, 0, 1046, 1047, 6, 107, 11, 0, 1047, 231, 1, 0, 0, 0, 1048, 1049, 3, 62, 23, 0, 1049, 1050, 1, 0, 0, 0, 1050, 1051, 6, 108, 11, 0, 1051, 233, 1, 0, 0, 0, 1052, 1053, 3, 78, 31, 0, 1053, 1054, 1, 0, 0, 0, 1054, 1055, 6, 109, 14, 0, 1055, 1056, 6, 109, 15, 0, 1056, 235, 1, 0, 0, 0, 1057, 1058, 3, 112, 48, 0, 1058, 1059, 1, 0, 0, 0, 1059, 1060, 6, 110, 18, 0, 1060, 237, 1, 0, 0, 0, 1061, 1062, 3, 116, 50, 0, 1062, 1063, 1, 0, 0, 0, 1063, 1064, 6, 111, 17, 0, 1064, 239, 1, 0, 0, 0, 1065, 1066, 3, 120, 52, 0, 1066, 1067, 1, 0, 0, 0, 1067, 1068, 6, 112, 21, 0, 1068, 241, 1, 0, 0, 0, 1069, 1070, 7, 12, 0, 0, 1070, 1071, 7, 2, 0, 0, 1071, 243, 1, 0, 0, 0, 1072, 1073, 3, 226, 105, 0, 1073, 1074, 1, 0, 0, 0, 1074, 1075, 6, 114, 22, 0, 1075, 245, 1, 0, 0, 0, 1076, 1077, 3, 58, 21, 0, 1077, 1078, 1, 0, 0, 0, 1078, 1079, 6, 115, 11, 0, 1079, 247, 1, 0, 0, 0, 1080, 1081, 3, 60, 22, 0, 1081, 1082, 1, 0, 0, 0, 1082, 1083, 6, 116, 11, 0, 1083, 249, 1, 0, 0, 0, 1084, 1085, 3, 62, 23, 0, 1085, 1086, 1, 0, 0, 0, 1086, 1087, 6, 117, 11, 0, 1087, 251, 1, 0, 0, 0, 1088, 1089, 3, 78, 31, 0, 1089, 1090, 1, 0, 0, 0, 1090, 1091, 6, 118, 14, 0, 1091, 1092, 6, 118, 15, 0, 1092, 253, 1, 0, 0, 0, 1093, 1094, 3, 178, 81, 0, 1094, 1095, 1, 0, 0, 0, 1095, 1096, 6, 119, 12, 0, 1096, 1097, 6, 119, 23, 0, 1097, 255, 1, 0, 0, 0, 1098, 1099, 7, 7, 0, 0, 1099, 1100, 7, 9, 0, 0, 1100, 1101, 1, 0, 0, 0, 1101, 1102, 6, 120, 24, 0, 1102, 257, 1, 0, 0, 0, 1103, 1104, 7, 20, 0, 0, 1104, 1105, 7, 1, 0, 0, 1105, 1106, 7, 5, 0, 0, 1106, 1107, 7, 10, 0, 0, 1107, 1108, 1, 0, 0, 0, 1108, 1109, 6, 121, 24, 0, 1109, 259, 1, 0, 0, 0, 1110, 1111, 8, 34, 0, 0, 1111, 261, 1, 0, 0, 0, 1112, 1114, 3, 260, 122, 0, 1113, 1112, 1, 0, 0, 0, 1114, 1115, 1, 0, 0, 0, 1115, 1113, 1, 0, 0, 0, 1115, 1116, 1, 0, 0, 0, 1116, 1117, 1, 0, 0, 0, 1117, 1118, 3, 360, 172, 0, 1118, 1120, 1, 0, 0, 0, 1119, 1113, 1, 0, 0, 0, 1119, 1120, 1, 0, 0, 0, 1120, 1122, 1, 0, 0, 0, 1121, 1123, 3, 260, 122, 0, 1122, 1121, 1, 0, 0, 0, 1123, 1124, 1, 0, 0, 0, 1124, 1122, 1, 0, 0, 0, 1124, 1125, 1, 0, 0, 0, 1125, 263, 1, 0, 0, 0, 1126, 1127, 3, 186, 85, 0, 1127, 1128, 1, 0, 0, 0, 1128, 1129, 6, 124, 25, 0, 1129, 265, 1, 0, 0, 0, 1130, 1131, 3, 262, 123, 0, 1131, 1132, 1, 0, 0, 0, 1132, 1133, 6, 125, 26, 0, 1133, 267, 1, 0, 0, 0, 1134, 1135, 3, 58, 21, 0, 1135, 1136, 1, 0, 0, 0, 1136, 1137, 6, 126, 11, 0, 1137, 269, 1, 0, 0, 0, 1138, 1139, 3, 60, 22, 0, 1139, 1140, 1, 0, 0, 0, 1140, 1141, 6, 127, 11, 0, 1141, 271, 1, 0, 0, 0, 1142, 1143, 3, 62, 23, 0, 1143, 1144, 1, 0, 0, 0, 1144, 1145, 6, 128, 11, 0, 1145, 273, 1, 0, 0, 0, 1146, 1147, 3, 78, 31, 0, 1147, 1148, 1, 0, 0, 0, 1148, 1149, 6, 129, 14, 0, 1149, 1150, 6, 129, 15, 0, 1150, 1151, 6, 129, 15, 0, 1151, 275, 1, 0, 0, 0, 1152, 1153, 3, 112, 48, 0, 1153, 1154, 1, 0, 0, 0, 1154, 1155, 6, 130, 18, 0, 1155, 277, 1, 0, 0, 0, 1156, 1157, 3, 116, 50, 0, 1157, 1158, 1, 0, 0, 0, 1158, 1159, 6, 131, 17, 0, 1159, 279, 1, 0, 0, 0, 1160, 1161, 3, 120, 52, 0, 1161, 1162, 1, 0, 0, 0, 1162, 1163, 6, 132, 21, 0, 1163, 281, 1, 0, 0, 0, 1164, 1165, 3, 258, 121, 0, 1165, 1166, 1, 0, 0, 0, 1166, 1167, 6, 133, 27, 0, 1167, 283, 1, 0, 0, 0, 1168, 1169, 3, 226, 105, 0, 1169, 1170, 1, 0, 0, 0, 1170, 1171, 6, 134, 22, 0, 1171, 285, 1, 0, 0, 0, 1172, 1173, 3, 186, 85, 0, 1173, 1174, 1, 0, 0, 0, 1174, 1175, 6, 135, 25, 0, 1175, 287, 1, 0, 0, 0, 1176, 1177, 3, 58, 21, 0, 1177, 1178, 1, 0, 0, 0, 1178, 1179, 6, 136, 11, 0, 1179, 289, 1, 0, 0, 0, 1180, 1181, 3, 60, 22, 0, 1181, 1182, 1, 0, 0, 0, 1182, 1183, 6, 137, 11, 0, 1183, 291, 1, 0, 0, 0, 1184, 1185, 3, 62, 23, 0, 1185, 1186, 1, 0, 0, 0, 1186, 1187, 6, 138, 11, 0, 1187, 293, 1, 0, 0, 0, 1188, 1189, 3, 78, 31, 0, 1189, 1190, 1, 0, 0, 0, 1190, 1191, 6, 139, 14, 0, 1191, 1192, 6, 139, 15, 0, 1192, 295, 1, 0, 0, 0, 1193, 1194, 3, 116, 50, 0, 1194, 1195, 1, 0, 0, 0, 1195, 1196, 6, 140, 17, 0, 1196, 297, 1, 0, 0, 0, 1197, 1198, 3, 120, 52, 0, 1198, 1199, 1, 0, 0, 0, 1199, 1200, 6, 141, 21, 0, 1200, 299, 1, 0, 0, 0, 1201, 1202, 3, 256, 120, 0, 1202, 1203, 1, 0, 0, 0, 1203, 1204, 6, 142, 28, 0, 1204, 1205, 6, 142, 29, 0, 1205, 301, 1, 0, 0, 0, 1206, 1207, 3, 66, 25, 0, 1207, 1208, 1, 0, 0, 0, 1208, 1209, 6, 143, 20, 0, 1209, 303, 1, 0, 0, 0, 1210, 1211, 3, 58, 21, 0, 1211, 1212, 1, 0, 0, 0, 1212, 1213, 6, 144, 11, 0, 1213, 305, 1, 0, 0, 0, 1214, 1215, 3, 60, 22, 0, 1215, 1216, 1, 0, 0, 0, 1216, 1217, 6, 145, 11, 0, 1217, 307, 1, 0, 0, 0, 1218, 1219, 3, 62, 23, 0, 1219, 1220, 1, 0, 0, 0, 1220, 1221, 6, 146, 11, 0, 1221, 309, 1, 0, 0, 0, 1222, 1223, 3, 78, 31, 0, 1223, 1224, 1, 0, 0, 0, 1224, 1225, 6, 147, 14, 0, 1225, 1226, 6, 147, 15, 0, 1226, 1227, 6, 147, 15, 0, 1227, 311, 1, 0, 0, 0, 1228, 1229, 3, 116, 50, 0, 1229, 1230, 1, 0, 0, 0, 1230, 1231, 6, 148, 17, 0, 1231, 313, 1, 0, 0, 0, 1232, 1233, 3, 120, 52, 0, 1233, 1234, 1, 0, 0, 0, 1234, 1235, 6, 149, 21, 0, 1235, 315, 1, 0, 0, 0, 1236, 1237, 3, 226, 105, 0, 1237, 1238, 1, 0, 0, 0, 1238, 1239, 6, 150, 22, 0, 1239, 317, 1, 0, 0, 0, 1240, 1241, 3, 58, 21, 0, 1241, 1242, 1, 0, 0, 0, 1242, 1243, 6, 151, 11, 0, 1243, 319, 1, 0, 0, 0, 1244, 1245, 3, 60, 22, 0, 1245, 1246, 1, 0, 0, 0, 1246, 1247, 6, 152, 11, 0, 1247, 321, 1, 0, 0, 0, 1248, 1249, 3, 62, 23, 0, 1249, 1250, 1, 0, 0, 0, 1250, 1251, 6, 153, 11, 0, 1251, 323, 1, 0, 0, 0, 1252, 1253, 3, 78, 31, 0, 1253, 1254, 1, 0, 0, 0, 1254, 1255, 6, 154, 14, 0, 1255, 1256, 6, 154, 15, 0, 1256, 325, 1, 0, 0, 0, 1257, 1258, 3, 120, 52, 0, 1258, 1259, 1, 0, 0, 0, 1259, 1260, 6, 155, 21, 0, 1260, 327, 1, 0, 0, 0, 1261, 1262, 3, 186, 85, 0, 1262, 1263, 1, 0, 0, 0, 1263, 1264, 6, 156, 25, 0, 1264, 329, 1, 0, 0, 0, 1265, 1266, 3, 182, 83, 0, 1266, 1267, 1, 0, 0, 0, 1267, 1268, 6, 157, 30, 0, 1268, 331, 1, 0, 0, 0, 1269, 1270, 3, 58, 21, 0, 1270, 1271, 1, 0, 0, 0, 1271, 1272, 6, 158, 11, 0, 1272, 333, 1, 0, 0, 0, 1273, 1274, 3, 60, 22, 0, 1274, 1275, 1, 0, 0, 0, 1275, 1276, 6, 159, 11, 0, 1276, 335, 1, 0, 0, 0, 1277, 1278, 3, 62, 23, 0, 1278, 1279, 1, 0, 0, 0, 1279, 1280, 6, 160, 11, 0, 1280, 337, 1, 0, 0, 0, 1281, 1282, 3, 78, 31, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1284, 6, 161, 14, 0, 1284, 1285, 6, 161, 15, 0, 1285, 339, 1, 0, 0, 0, 1286, 1287, 7, 1, 0, 0, 1287, 1288, 7, 9, 0, 0, 1288, 1289, 7, 15, 0, 0, 1289, 1290, 7, 7, 0, 0, 1290, 341, 1, 0, 0, 0, 1291, 1292, 3, 58, 21, 0, 1292, 1293, 1, 0, 0, 0, 1293, 1294, 6, 163, 11, 0, 1294, 343, 1, 0, 0, 0, 1295, 1296, 3, 60, 22, 0, 1296, 1297, 1, 0, 0, 0, 1297, 1298, 6, 164, 11, 0, 1298, 345, 1, 0, 0, 0, 1299, 1300, 3, 62, 23, 0, 1300, 1301, 1, 0, 0, 0, 1301, 1302, 6, 165, 11, 0, 1302, 347, 1, 0, 0, 0, 1303, 1304, 3, 78, 31, 0, 1304, 1305, 1, 0, 0, 0, 1305, 1306, 6, 166, 14, 0, 1306, 1307, 6, 166, 15, 0, 1307, 349, 1, 0, 0, 0, 1308, 1309, 7, 15, 0, 0, 1309, 1310, 7, 19, 0, 0, 1310, 1311, 7, 9, 0, 0, 1311, 1312, 7, 4, 0, 0, 1312, 1313, 7, 5, 0, 0, 1313, 1314, 7, 1, 0, 0, 1314, 1315, 7, 7, 0, 0, 1315, 1316, 7, 9, 0, 0, 1316, 1317, 7, 2, 0, 0, 1317, 351, 1, 0, 0, 0, 1318, 1319, 3, 58, 21, 0, 1319, 1320, 1, 0, 0, 0, 1320, 1321, 6, 168, 11, 0, 1321, 353, 1, 0, 0, 0, 1322, 1323, 3, 60, 22, 0, 1323, 1324, 1, 0, 0, 0, 1324, 1325, 6, 169, 11, 0, 1325, 355, 1, 0, 0, 0, 1326, 1327, 3, 62, 23, 0, 1327, 1328, 1, 0, 0, 0, 1328, 1329, 6, 170, 11, 0, 1329, 357, 1, 0, 0, 0, 1330, 1331, 3, 180, 82, 0, 1331, 1332, 1, 0, 0, 0, 1332, 1333, 6, 171, 16, 0, 1333, 1334, 6, 171, 15, 0, 1334, 359, 1, 0, 0, 0, 1335, 1336, 5, 58, 0, 0, 1336, 361, 1, 0, 0, 0, 1337, 1343, 3, 90, 37, 0, 1338, 1343, 3, 80, 32, 0, 1339, 1343, 3, 120, 52, 0, 1340, 1343, 3, 82, 33, 0, 1341, 1343, 3, 96, 40, 0, 1342, 1337, 1, 0, 0, 0, 1342, 1338, 1, 0, 0, 0, 1342, 1339, 1, 0, 0, 0, 1342, 1340, 1, 0, 0, 0, 1342, 1341, 1, 0, 0, 0, 1343, 1344, 1, 0, 0, 0, 1344, 1342, 1, 0, 0, 0, 1344, 1345, 1, 0, 0, 0, 1345, 363, 1, 0, 0, 0, 1346, 1347, 3, 58, 21, 0, 1347, 1348, 1, 0, 0, 0, 1348, 1349, 6, 174, 11, 0, 1349, 365, 1, 0, 0, 0, 1350, 1351, 3, 60, 22, 0, 1351, 1352, 1, 0, 0, 0, 1352, 1353, 6, 175, 11, 0, 1353, 367, 1, 0, 0, 0, 1354, 1355, 3, 62, 23, 0, 1355, 1356, 1, 0, 0, 0, 1356, 1357, 6, 176, 11, 0, 1357, 369, 1, 0, 0, 0, 1358, 1359, 3, 78, 31, 0, 1359, 1360, 1, 0, 0, 0, 1360, 1361, 6, 177, 14, 0, 1361, 1362, 6, 177, 15, 0, 1362, 371, 1, 0, 0, 0, 1363, 1364, 3, 66, 25, 0, 1364, 1365, 1, 0, 0, 0, 1365, 1366, 6, 178, 20, 0, 1366, 1367, 6, 178, 15, 0, 1367, 1368, 6, 178, 31, 0, 1368, 373, 1, 0, 0, 0, 1369, 1370, 3, 58, 21, 0, 1370, 1371, 1, 0, 0, 0, 1371, 1372, 6, 179, 11, 0, 1372, 375, 1, 0, 0, 0, 1373, 1374, 3, 60, 22, 0, 1374, 1375, 1, 0, 0, 0, 1375, 1376, 6, 180, 11, 0, 1376, 377, 1, 0, 0, 0, 1377, 1378, 3, 62, 23, 0, 1378, 1379, 1, 0, 0, 0, 1379, 1380, 6, 181, 11, 0, 1380, 379, 1, 0, 0, 0, 1381, 1382, 3, 116, 50, 0, 1382, 1383, 1, 0, 0, 0, 1383, 1384, 6, 182, 17, 0, 1384, 1385, 6, 182, 15, 0, 1385, 1386, 6, 182, 7, 0, 1386, 381, 1, 0, 0, 0, 1387, 1388, 3, 58, 21, 0, 1388, 1389, 1, 0, 0, 0, 1389, 1390, 6, 183, 11, 0, 1390, 383, 1, 0, 0, 0, 1391, 1392, 3, 60, 22, 0, 1392, 1393, 1, 0, 0, 0, 1393, 1394, 6, 184, 11, 0, 1394, 385, 1, 0, 0, 0, 1395, 1396, 3, 62, 23, 0, 1396, 1397, 1, 0, 0, 0, 1397, 1398, 6, 185, 11, 0, 1398, 387, 1, 0, 0, 0, 1399, 1400, 3, 186, 85, 0, 1400, 1401, 1, 0, 0, 0, 1401, 1402, 6, 186, 15, 0, 1402, 1403, 6, 186, 0, 0, 1403, 1404, 6, 186, 25, 0, 1404, 389, 1, 0, 0, 0, 1405, 1406, 3, 182, 83, 0, 1406, 1407, 1, 0, 0, 0, 1407, 1408, 6, 187, 15, 0, 1408, 1409, 6, 187, 0, 0, 1409, 1410, 6, 187, 30, 0, 1410, 391, 1, 0, 0, 0, 1411, 1412, 3, 106, 45, 0, 1412, 1413, 1, 0, 0, 0, 1413, 1414, 6, 188, 15, 0, 1414, 1415, 6, 188, 0, 0, 1415, 1416, 6, 188, 32, 0, 1416, 393, 1, 0, 0, 0, 1417, 1418, 3, 78, 31, 0, 1418, 1419, 1, 0, 0, 0, 1419, 1420, 6, 189, 14, 0, 1420, 1421, 6, 189, 15, 0, 1421, 395, 1, 0, 0, 0, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 568, 578, 582, 585, 594, 596, 607, 614, 619, 658, 663, 672, 679, 684, 686, 697, 705, 708, 710, 715, 720, 726, 733, 738, 744, 747, 755, 759, 883, 890, 892, 908, 913, 918, 920, 926, 1011, 1015, 1020, 1025, 1030, 1032, 1036, 1038, 1115, 1119, 1124, 1342, 1344, 33, 5, 2, 0, 5, 4, 0, 5, 6, 0, 5, 1, 0, 5, 3, 0, 5, 8, 0, 5, 12, 0, 5, 14, 0, 5, 10, 0, 5, 5, 0, 5, 11, 0, 0, 1, 0, 7, 69, 0, 5, 0, 0, 7, 29, 0, 4, 0, 0, 7, 70, 0, 7, 38, 0, 7, 36, 0, 7, 30, 0, 7, 25, 0, 7, 40, 0, 7, 80, 0, 5, 13, 0, 5, 7, 0, 7, 72, 0, 7, 90, 0, 7, 89, 0, 7, 88, 0, 5, 9, 0, 7, 71, 0, 5, 15, 0, 7, 33, 0] \ No newline at end of file diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens b/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens index 30ce0d5eea55b..04798fc3dca8a 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens @@ -65,62 +65,63 @@ MINUS=64 ASTERISK=65 SLASH=66 PERCENT=67 -OPENING_BRACKET=68 -CLOSING_BRACKET=69 -UNQUOTED_IDENTIFIER=70 -QUOTED_IDENTIFIER=71 -EXPR_LINE_COMMENT=72 -EXPR_MULTILINE_COMMENT=73 -EXPR_WS=74 -METADATA=75 -FROM_LINE_COMMENT=76 -FROM_MULTILINE_COMMENT=77 -FROM_WS=78 -ID_PATTERN=79 -PROJECT_LINE_COMMENT=80 -PROJECT_MULTILINE_COMMENT=81 -PROJECT_WS=82 -AS=83 -RENAME_LINE_COMMENT=84 -RENAME_MULTILINE_COMMENT=85 -RENAME_WS=86 -ON=87 -WITH=88 -ENRICH_POLICY_NAME=89 -ENRICH_LINE_COMMENT=90 -ENRICH_MULTILINE_COMMENT=91 -ENRICH_WS=92 -ENRICH_FIELD_LINE_COMMENT=93 -ENRICH_FIELD_MULTILINE_COMMENT=94 -ENRICH_FIELD_WS=95 -LOOKUP_LINE_COMMENT=96 -LOOKUP_MULTILINE_COMMENT=97 -LOOKUP_WS=98 -LOOKUP_FIELD_LINE_COMMENT=99 -LOOKUP_FIELD_MULTILINE_COMMENT=100 -LOOKUP_FIELD_WS=101 -MVEXPAND_LINE_COMMENT=102 -MVEXPAND_MULTILINE_COMMENT=103 -MVEXPAND_WS=104 -INFO=105 -SHOW_LINE_COMMENT=106 -SHOW_MULTILINE_COMMENT=107 -SHOW_WS=108 -FUNCTIONS=109 -META_LINE_COMMENT=110 -META_MULTILINE_COMMENT=111 -META_WS=112 -COLON=113 -SETTING=114 -SETTING_LINE_COMMENT=115 -SETTTING_MULTILINE_COMMENT=116 -SETTING_WS=117 -METRICS_LINE_COMMENT=118 -METRICS_MULTILINE_COMMENT=119 -METRICS_WS=120 -CLOSING_METRICS_LINE_COMMENT=121 -CLOSING_METRICS_MULTILINE_COMMENT=122 -CLOSING_METRICS_WS=123 +NAMED_OR_POSITIONAL_PARAM=68 +OPENING_BRACKET=69 +CLOSING_BRACKET=70 +UNQUOTED_IDENTIFIER=71 +QUOTED_IDENTIFIER=72 +EXPR_LINE_COMMENT=73 +EXPR_MULTILINE_COMMENT=74 +EXPR_WS=75 +METADATA=76 +FROM_LINE_COMMENT=77 +FROM_MULTILINE_COMMENT=78 +FROM_WS=79 +ID_PATTERN=80 +PROJECT_LINE_COMMENT=81 +PROJECT_MULTILINE_COMMENT=82 +PROJECT_WS=83 +AS=84 +RENAME_LINE_COMMENT=85 +RENAME_MULTILINE_COMMENT=86 +RENAME_WS=87 +ON=88 +WITH=89 +ENRICH_POLICY_NAME=90 +ENRICH_LINE_COMMENT=91 +ENRICH_MULTILINE_COMMENT=92 +ENRICH_WS=93 +ENRICH_FIELD_LINE_COMMENT=94 +ENRICH_FIELD_MULTILINE_COMMENT=95 +ENRICH_FIELD_WS=96 +LOOKUP_LINE_COMMENT=97 +LOOKUP_MULTILINE_COMMENT=98 +LOOKUP_WS=99 +LOOKUP_FIELD_LINE_COMMENT=100 +LOOKUP_FIELD_MULTILINE_COMMENT=101 +LOOKUP_FIELD_WS=102 +MVEXPAND_LINE_COMMENT=103 +MVEXPAND_MULTILINE_COMMENT=104 +MVEXPAND_WS=105 +INFO=106 +SHOW_LINE_COMMENT=107 +SHOW_MULTILINE_COMMENT=108 +SHOW_WS=109 +FUNCTIONS=110 +META_LINE_COMMENT=111 +META_MULTILINE_COMMENT=112 +META_WS=113 +COLON=114 +SETTING=115 +SETTING_LINE_COMMENT=116 +SETTTING_MULTILINE_COMMENT=117 +SETTING_WS=118 +METRICS_LINE_COMMENT=119 +METRICS_MULTILINE_COMMENT=120 +METRICS_WS=121 +CLOSING_METRICS_LINE_COMMENT=122 +CLOSING_METRICS_MULTILINE_COMMENT=123 +CLOSING_METRICS_WS=124 'dissect'=1 'drop'=2 'enrich'=3 @@ -177,11 +178,11 @@ CLOSING_METRICS_WS=123 '*'=65 '/'=66 '%'=67 -']'=69 -'metadata'=75 -'as'=83 -'on'=87 -'with'=88 -'info'=105 -'functions'=109 -':'=113 +']'=70 +'metadata'=76 +'as'=84 +'on'=88 +'with'=89 +'info'=106 +'functions'=110 +':'=114 diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.ts b/packages/kbn-esql-ast/src/antlr/esql_lexer.ts index 4dd20eceeb217..ff985e02ccf1d 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.ts +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.ts @@ -80,62 +80,63 @@ export default class esql_lexer extends Lexer { public static readonly ASTERISK = 65; public static readonly SLASH = 66; public static readonly PERCENT = 67; - public static readonly OPENING_BRACKET = 68; - public static readonly CLOSING_BRACKET = 69; - public static readonly UNQUOTED_IDENTIFIER = 70; - public static readonly QUOTED_IDENTIFIER = 71; - public static readonly EXPR_LINE_COMMENT = 72; - public static readonly EXPR_MULTILINE_COMMENT = 73; - public static readonly EXPR_WS = 74; - public static readonly METADATA = 75; - public static readonly FROM_LINE_COMMENT = 76; - public static readonly FROM_MULTILINE_COMMENT = 77; - public static readonly FROM_WS = 78; - public static readonly ID_PATTERN = 79; - public static readonly PROJECT_LINE_COMMENT = 80; - public static readonly PROJECT_MULTILINE_COMMENT = 81; - public static readonly PROJECT_WS = 82; - public static readonly AS = 83; - public static readonly RENAME_LINE_COMMENT = 84; - public static readonly RENAME_MULTILINE_COMMENT = 85; - public static readonly RENAME_WS = 86; - public static readonly ON = 87; - public static readonly WITH = 88; - public static readonly ENRICH_POLICY_NAME = 89; - public static readonly ENRICH_LINE_COMMENT = 90; - public static readonly ENRICH_MULTILINE_COMMENT = 91; - public static readonly ENRICH_WS = 92; - public static readonly ENRICH_FIELD_LINE_COMMENT = 93; - public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 94; - public static readonly ENRICH_FIELD_WS = 95; - public static readonly LOOKUP_LINE_COMMENT = 96; - public static readonly LOOKUP_MULTILINE_COMMENT = 97; - public static readonly LOOKUP_WS = 98; - public static readonly LOOKUP_FIELD_LINE_COMMENT = 99; - public static readonly LOOKUP_FIELD_MULTILINE_COMMENT = 100; - public static readonly LOOKUP_FIELD_WS = 101; - public static readonly MVEXPAND_LINE_COMMENT = 102; - public static readonly MVEXPAND_MULTILINE_COMMENT = 103; - public static readonly MVEXPAND_WS = 104; - public static readonly INFO = 105; - public static readonly SHOW_LINE_COMMENT = 106; - public static readonly SHOW_MULTILINE_COMMENT = 107; - public static readonly SHOW_WS = 108; - public static readonly FUNCTIONS = 109; - public static readonly META_LINE_COMMENT = 110; - public static readonly META_MULTILINE_COMMENT = 111; - public static readonly META_WS = 112; - public static readonly COLON = 113; - public static readonly SETTING = 114; - public static readonly SETTING_LINE_COMMENT = 115; - public static readonly SETTTING_MULTILINE_COMMENT = 116; - public static readonly SETTING_WS = 117; - public static readonly METRICS_LINE_COMMENT = 118; - public static readonly METRICS_MULTILINE_COMMENT = 119; - public static readonly METRICS_WS = 120; - public static readonly CLOSING_METRICS_LINE_COMMENT = 121; - public static readonly CLOSING_METRICS_MULTILINE_COMMENT = 122; - public static readonly CLOSING_METRICS_WS = 123; + public static readonly NAMED_OR_POSITIONAL_PARAM = 68; + public static readonly OPENING_BRACKET = 69; + public static readonly CLOSING_BRACKET = 70; + public static readonly UNQUOTED_IDENTIFIER = 71; + public static readonly QUOTED_IDENTIFIER = 72; + public static readonly EXPR_LINE_COMMENT = 73; + public static readonly EXPR_MULTILINE_COMMENT = 74; + public static readonly EXPR_WS = 75; + public static readonly METADATA = 76; + public static readonly FROM_LINE_COMMENT = 77; + public static readonly FROM_MULTILINE_COMMENT = 78; + public static readonly FROM_WS = 79; + public static readonly ID_PATTERN = 80; + public static readonly PROJECT_LINE_COMMENT = 81; + public static readonly PROJECT_MULTILINE_COMMENT = 82; + public static readonly PROJECT_WS = 83; + public static readonly AS = 84; + public static readonly RENAME_LINE_COMMENT = 85; + public static readonly RENAME_MULTILINE_COMMENT = 86; + public static readonly RENAME_WS = 87; + public static readonly ON = 88; + public static readonly WITH = 89; + public static readonly ENRICH_POLICY_NAME = 90; + public static readonly ENRICH_LINE_COMMENT = 91; + public static readonly ENRICH_MULTILINE_COMMENT = 92; + public static readonly ENRICH_WS = 93; + public static readonly ENRICH_FIELD_LINE_COMMENT = 94; + public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 95; + public static readonly ENRICH_FIELD_WS = 96; + public static readonly LOOKUP_LINE_COMMENT = 97; + public static readonly LOOKUP_MULTILINE_COMMENT = 98; + public static readonly LOOKUP_WS = 99; + public static readonly LOOKUP_FIELD_LINE_COMMENT = 100; + public static readonly LOOKUP_FIELD_MULTILINE_COMMENT = 101; + public static readonly LOOKUP_FIELD_WS = 102; + public static readonly MVEXPAND_LINE_COMMENT = 103; + public static readonly MVEXPAND_MULTILINE_COMMENT = 104; + public static readonly MVEXPAND_WS = 105; + public static readonly INFO = 106; + public static readonly SHOW_LINE_COMMENT = 107; + public static readonly SHOW_MULTILINE_COMMENT = 108; + public static readonly SHOW_WS = 109; + public static readonly FUNCTIONS = 110; + public static readonly META_LINE_COMMENT = 111; + public static readonly META_MULTILINE_COMMENT = 112; + public static readonly META_WS = 113; + public static readonly COLON = 114; + public static readonly SETTING = 115; + public static readonly SETTING_LINE_COMMENT = 116; + public static readonly SETTTING_MULTILINE_COMMENT = 117; + public static readonly SETTING_WS = 118; + public static readonly METRICS_LINE_COMMENT = 119; + public static readonly METRICS_MULTILINE_COMMENT = 120; + public static readonly METRICS_WS = 121; + public static readonly CLOSING_METRICS_LINE_COMMENT = 122; + public static readonly CLOSING_METRICS_MULTILINE_COMMENT = 123; + public static readonly CLOSING_METRICS_WS = 124; public static readonly EOF = Token.EOF; public static readonly EXPLAIN_MODE = 1; public static readonly EXPRESSION_MODE = 2; @@ -190,10 +191,11 @@ export default class esql_lexer extends Lexer { "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", - null, "']'", null, null, + "']'", null, null, null, - null, "'metadata'", + null, null, + "'metadata'", null, null, null, null, null, null, @@ -253,6 +255,7 @@ export default class esql_lexer extends Lexer { "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", + "NAMED_OR_POSITIONAL_PARAM", "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", @@ -326,29 +329,29 @@ export default class esql_lexer extends Lexer { "ASSIGN", "CAST_OP", "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "EQ", "CIEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", - "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", - "UNQUOTED_IDENTIFIER", "QUOTED_ID", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", - "EXPR_MULTILINE_COMMENT", "EXPR_WS", "FROM_PIPE", "FROM_OPENING_BRACKET", - "FROM_CLOSING_BRACKET", "FROM_COMMA", "FROM_ASSIGN", "FROM_QUOTED_STRING", - "METADATA", "FROM_INDEX_UNQUOTED_IDENTIFIER", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", - "FROM_WS", "PROJECT_PIPE", "PROJECT_DOT", "PROJECT_COMMA", "UNQUOTED_ID_BODY_WITH_PATTERN", - "UNQUOTED_ID_PATTERN", "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", - "PROJECT_WS", "RENAME_PIPE", "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", - "AS", "RENAME_ID_PATTERN", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", - "RENAME_WS", "ENRICH_PIPE", "ENRICH_OPENING_BRACKET", "ON", "WITH", "ENRICH_POLICY_NAME_BODY", - "ENRICH_POLICY_NAME", "ENRICH_QUOTED_IDENTIFIER", "ENRICH_MODE_UNQUOTED_VALUE", - "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", - "ENRICH_FIELD_ASSIGN", "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", - "ENRICH_FIELD_ID_PATTERN", "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_LINE_COMMENT", - "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "LOOKUP_PIPE", "LOOKUP_COMMA", - "LOOKUP_DOT", "LOOKUP_ON", "LOOKUP_INDEX_UNQUOTED_IDENTIFIER", "LOOKUP_LINE_COMMENT", - "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", "LOOKUP_FIELD_PIPE", "LOOKUP_FIELD_COMMA", - "LOOKUP_FIELD_DOT", "LOOKUP_FIELD_ID_PATTERN", "LOOKUP_FIELD_LINE_COMMENT", - "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", "MVEXPAND_PIPE", - "MVEXPAND_DOT", "MVEXPAND_QUOTED_IDENTIFIER", "MVEXPAND_UNQUOTED_IDENTIFIER", - "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", - "SHOW_PIPE", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", "SHOW_WS", - "META_PIPE", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", + "ASTERISK", "SLASH", "PERCENT", "NAMED_OR_POSITIONAL_PARAM", "OPENING_BRACKET", + "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_ID", "QUOTED_IDENTIFIER", + "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", "FROM_PIPE", + "FROM_OPENING_BRACKET", "FROM_CLOSING_BRACKET", "FROM_COMMA", "FROM_ASSIGN", + "FROM_QUOTED_STRING", "METADATA", "FROM_INDEX_UNQUOTED_IDENTIFIER", "FROM_LINE_COMMENT", + "FROM_MULTILINE_COMMENT", "FROM_WS", "PROJECT_PIPE", "PROJECT_DOT", "PROJECT_COMMA", + "UNQUOTED_ID_BODY_WITH_PATTERN", "UNQUOTED_ID_PATTERN", "ID_PATTERN", + "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", "RENAME_PIPE", + "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", "AS", "RENAME_ID_PATTERN", + "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", "ENRICH_PIPE", + "ENRICH_OPENING_BRACKET", "ON", "WITH", "ENRICH_POLICY_NAME_BODY", "ENRICH_POLICY_NAME", + "ENRICH_QUOTED_IDENTIFIER", "ENRICH_MODE_UNQUOTED_VALUE", "ENRICH_LINE_COMMENT", + "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", "ENRICH_FIELD_ASSIGN", + "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", "ENRICH_FIELD_ID_PATTERN", + "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", + "ENRICH_FIELD_WS", "LOOKUP_PIPE", "LOOKUP_COMMA", "LOOKUP_DOT", "LOOKUP_ON", + "LOOKUP_INDEX_UNQUOTED_IDENTIFIER", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", + "LOOKUP_WS", "LOOKUP_FIELD_PIPE", "LOOKUP_FIELD_COMMA", "LOOKUP_FIELD_DOT", + "LOOKUP_FIELD_ID_PATTERN", "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", + "LOOKUP_FIELD_WS", "MVEXPAND_PIPE", "MVEXPAND_DOT", "MVEXPAND_QUOTED_IDENTIFIER", + "MVEXPAND_UNQUOTED_IDENTIFIER", "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", + "MVEXPAND_WS", "SHOW_PIPE", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", + "SHOW_WS", "META_PIPE", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", "META_WS", "SETTING_CLOSING_BRACKET", "COLON", "SETTING", "SETTING_LINE_COMMENT", "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "METRICS_PIPE", "METRICS_INDEX_UNQUOTED_IDENTIFIER", "METRICS_LINE_COMMENT", "METRICS_MULTILINE_COMMENT", "METRICS_WS", "CLOSING_METRICS_COMMA", @@ -375,7 +378,7 @@ export default class esql_lexer extends Lexer { public get modeNames(): string[] { return esql_lexer.modeNames; } - public static readonly _serializedATN: number[] = [4,0,123,1404,6,-1,6, + public static readonly _serializedATN: number[] = [4,0,124,1422,6,-1,6, -1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1, 2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8, 2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16, @@ -405,456 +408,463 @@ export default class esql_lexer extends Lexer { 2,169,7,169,2,170,7,170,2,171,7,171,2,172,7,172,2,173,7,173,2,174,7,174, 2,175,7,175,2,176,7,176,2,177,7,177,2,178,7,178,2,179,7,179,2,180,7,180, 2,181,7,181,2,182,7,182,2,183,7,183,2,184,7,184,2,185,7,185,2,186,7,186, - 2,187,7,187,2,188,7,188,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3, - 1,3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5, - 1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7, - 1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9, - 1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11, - 1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,13,1, - 13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,14, - 1,14,1,14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,16,1,16,1,16,1, - 16,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,18,1,18,1,18,1,18, - 1,18,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,19,1,19,1,19,1,20,4,20,565, - 8,20,11,20,12,20,566,1,20,1,20,1,21,1,21,1,21,1,21,5,21,575,8,21,10,21, - 12,21,578,9,21,1,21,3,21,581,8,21,1,21,3,21,584,8,21,1,21,1,21,1,22,1,22, - 1,22,1,22,1,22,5,22,593,8,22,10,22,12,22,596,9,22,1,22,1,22,1,22,1,22,1, - 22,1,23,4,23,604,8,23,11,23,12,23,605,1,23,1,23,1,24,1,24,1,24,3,24,613, - 8,24,1,25,4,25,616,8,25,11,25,12,25,617,1,26,1,26,1,26,1,26,1,26,1,27,1, - 27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,1,29,1,29,1,29,1,29,1,30,1,30,1,30, - 1,30,1,31,1,31,1,31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,34,1,35,1,35,1, - 36,1,36,3,36,657,8,36,1,36,4,36,660,8,36,11,36,12,36,661,1,37,1,37,1,38, - 1,38,1,39,1,39,1,39,3,39,671,8,39,1,40,1,40,1,41,1,41,1,41,3,41,678,8,41, - 1,42,1,42,1,42,5,42,683,8,42,10,42,12,42,686,9,42,1,42,1,42,1,42,1,42,1, - 42,1,42,5,42,694,8,42,10,42,12,42,697,9,42,1,42,1,42,1,42,1,42,1,42,3,42, - 704,8,42,1,42,3,42,707,8,42,3,42,709,8,42,1,43,4,43,712,8,43,11,43,12,43, - 713,1,44,4,44,717,8,44,11,44,12,44,718,1,44,1,44,5,44,723,8,44,10,44,12, - 44,726,9,44,1,44,1,44,4,44,730,8,44,11,44,12,44,731,1,44,4,44,735,8,44, - 11,44,12,44,736,1,44,1,44,5,44,741,8,44,10,44,12,44,744,9,44,3,44,746,8, - 44,1,44,1,44,1,44,1,44,4,44,752,8,44,11,44,12,44,753,1,44,1,44,3,44,758, - 8,44,1,45,1,45,1,45,1,46,1,46,1,46,1,46,1,47,1,47,1,47,1,47,1,48,1,48,1, - 49,1,49,1,49,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1,52,1,52,1,53,1,53,1,53, - 1,53,1,53,1,53,1,54,1,54,1,54,1,54,1,54,1,54,1,55,1,55,1,55,1,55,1,55,1, - 56,1,56,1,57,1,57,1,57,1,58,1,58,1,58,1,59,1,59,1,59,1,59,1,59,1,60,1,60, - 1,60,1,60,1,61,1,61,1,61,1,61,1,61,1,62,1,62,1,62,1,62,1,62,1,62,1,63,1, - 63,1,63,1,64,1,64,1,65,1,65,1,65,1,65,1,65,1,65,1,66,1,66,1,67,1,67,1,67, - 1,67,1,67,1,68,1,68,1,68,1,69,1,69,1,69,1,70,1,70,1,70,1,71,1,71,1,72,1, - 72,1,72,1,73,1,73,1,74,1,74,1,74,1,75,1,75,1,76,1,76,1,77,1,77,1,78,1,78, - 1,79,1,79,1,80,1,80,1,80,1,80,1,80,1,81,1,81,1,81,1,81,1,81,1,82,1,82,5, - 82,889,8,82,10,82,12,82,892,9,82,1,82,1,82,3,82,896,8,82,1,82,4,82,899, - 8,82,11,82,12,82,900,3,82,903,8,82,1,83,1,83,4,83,907,8,83,11,83,12,83, - 908,1,83,1,83,1,84,1,84,1,85,1,85,1,85,1,85,1,86,1,86,1,86,1,86,1,87,1, - 87,1,87,1,87,1,88,1,88,1,88,1,88,1,88,1,89,1,89,1,89,1,89,1,90,1,90,1,90, - 1,90,1,91,1,91,1,91,1,91,1,92,1,92,1,92,1,92,1,93,1,93,1,93,1,93,1,94,1, - 94,1,94,1,94,1,94,1,94,1,94,1,94,1,94,1,95,1,95,1,95,1,95,1,96,1,96,1,96, - 1,96,1,97,1,97,1,97,1,97,1,98,1,98,1,98,1,98,1,99,1,99,1,99,1,99,1,99,1, - 100,1,100,1,100,1,100,1,101,1,101,1,101,1,101,1,102,1,102,1,102,1,102,3, - 102,994,8,102,1,103,1,103,3,103,998,8,103,1,103,5,103,1001,8,103,10,103, - 12,103,1004,9,103,1,103,1,103,3,103,1008,8,103,1,103,4,103,1011,8,103,11, - 103,12,103,1012,3,103,1015,8,103,1,104,1,104,4,104,1019,8,104,11,104,12, - 104,1020,1,105,1,105,1,105,1,105,1,106,1,106,1,106,1,106,1,107,1,107,1, - 107,1,107,1,108,1,108,1,108,1,108,1,108,1,109,1,109,1,109,1,109,1,110,1, - 110,1,110,1,110,1,111,1,111,1,111,1,111,1,112,1,112,1,112,1,113,1,113,1, - 113,1,113,1,114,1,114,1,114,1,114,1,115,1,115,1,115,1,115,1,116,1,116,1, - 116,1,116,1,117,1,117,1,117,1,117,1,117,1,118,1,118,1,118,1,118,1,118,1, - 119,1,119,1,119,1,119,1,119,1,120,1,120,1,120,1,120,1,120,1,120,1,120,1, - 121,1,121,1,122,4,122,1096,8,122,11,122,12,122,1097,1,122,1,122,3,122,1102, - 8,122,1,122,4,122,1105,8,122,11,122,12,122,1106,1,123,1,123,1,123,1,123, - 1,124,1,124,1,124,1,124,1,125,1,125,1,125,1,125,1,126,1,126,1,126,1,126, - 1,127,1,127,1,127,1,127,1,128,1,128,1,128,1,128,1,128,1,128,1,129,1,129, - 1,129,1,129,1,130,1,130,1,130,1,130,1,131,1,131,1,131,1,131,1,132,1,132, - 1,132,1,132,1,133,1,133,1,133,1,133,1,134,1,134,1,134,1,134,1,135,1,135, - 1,135,1,135,1,136,1,136,1,136,1,136,1,137,1,137,1,137,1,137,1,138,1,138, - 1,138,1,138,1,138,1,139,1,139,1,139,1,139,1,140,1,140,1,140,1,140,1,141, - 1,141,1,141,1,141,1,141,1,142,1,142,1,142,1,142,1,143,1,143,1,143,1,143, - 1,144,1,144,1,144,1,144,1,145,1,145,1,145,1,145,1,146,1,146,1,146,1,146, - 1,146,1,146,1,147,1,147,1,147,1,147,1,148,1,148,1,148,1,148,1,149,1,149, - 1,149,1,149,1,150,1,150,1,150,1,150,1,151,1,151,1,151,1,151,1,152,1,152, - 1,152,1,152,1,153,1,153,1,153,1,153,1,153,1,154,1,154,1,154,1,154,1,155, - 1,155,1,155,1,155,1,156,1,156,1,156,1,156,1,157,1,157,1,157,1,157,1,158, - 1,158,1,158,1,158,1,159,1,159,1,159,1,159,1,160,1,160,1,160,1,160,1,160, - 1,161,1,161,1,161,1,161,1,161,1,162,1,162,1,162,1,162,1,163,1,163,1,163, - 1,163,1,164,1,164,1,164,1,164,1,165,1,165,1,165,1,165,1,165,1,166,1,166, - 1,166,1,166,1,166,1,166,1,166,1,166,1,166,1,166,1,167,1,167,1,167,1,167, - 1,168,1,168,1,168,1,168,1,169,1,169,1,169,1,169,1,170,1,170,1,170,1,170, - 1,170,1,171,1,171,1,172,1,172,1,172,1,172,1,172,4,172,1325,8,172,11,172, - 12,172,1326,1,173,1,173,1,173,1,173,1,174,1,174,1,174,1,174,1,175,1,175, - 1,175,1,175,1,176,1,176,1,176,1,176,1,176,1,177,1,177,1,177,1,177,1,177, - 1,177,1,178,1,178,1,178,1,178,1,179,1,179,1,179,1,179,1,180,1,180,1,180, - 1,180,1,181,1,181,1,181,1,181,1,181,1,181,1,182,1,182,1,182,1,182,1,183, - 1,183,1,183,1,183,1,184,1,184,1,184,1,184,1,185,1,185,1,185,1,185,1,185, - 1,185,1,186,1,186,1,186,1,186,1,186,1,186,1,187,1,187,1,187,1,187,1,187, - 1,187,1,188,1,188,1,188,1,188,1,188,2,594,695,0,189,16,1,18,2,20,3,22,4, - 24,5,26,6,28,7,30,8,32,9,34,10,36,11,38,12,40,13,42,14,44,15,46,16,48,17, - 50,18,52,19,54,20,56,21,58,22,60,23,62,24,64,0,66,25,68,0,70,0,72,26,74, - 27,76,28,78,29,80,0,82,0,84,0,86,0,88,0,90,0,92,0,94,0,96,0,98,0,100,30, - 102,31,104,32,106,33,108,34,110,35,112,36,114,37,116,38,118,39,120,40,122, - 41,124,42,126,43,128,44,130,45,132,46,134,47,136,48,138,49,140,50,142,51, - 144,52,146,53,148,54,150,55,152,56,154,57,156,58,158,59,160,60,162,61,164, - 62,166,63,168,64,170,65,172,66,174,67,176,68,178,69,180,70,182,0,184,71, - 186,72,188,73,190,74,192,0,194,0,196,0,198,0,200,0,202,0,204,75,206,0,208, - 76,210,77,212,78,214,0,216,0,218,0,220,0,222,0,224,79,226,80,228,81,230, - 82,232,0,234,0,236,0,238,0,240,83,242,0,244,84,246,85,248,86,250,0,252, - 0,254,87,256,88,258,0,260,89,262,0,264,0,266,90,268,91,270,92,272,0,274, - 0,276,0,278,0,280,0,282,0,284,0,286,93,288,94,290,95,292,0,294,0,296,0, - 298,0,300,0,302,96,304,97,306,98,308,0,310,0,312,0,314,0,316,99,318,100, - 320,101,322,0,324,0,326,0,328,0,330,102,332,103,334,104,336,0,338,105,340, - 106,342,107,344,108,346,0,348,109,350,110,352,111,354,112,356,0,358,113, - 360,114,362,115,364,116,366,117,368,0,370,0,372,118,374,119,376,120,378, - 0,380,121,382,122,384,123,386,0,388,0,390,0,392,0,16,0,1,2,3,4,5,6,7,8, - 9,10,11,12,13,14,15,35,2,0,68,68,100,100,2,0,73,73,105,105,2,0,83,83,115, - 115,2,0,69,69,101,101,2,0,67,67,99,99,2,0,84,84,116,116,2,0,82,82,114,114, - 2,0,79,79,111,111,2,0,80,80,112,112,2,0,78,78,110,110,2,0,72,72,104,104, - 2,0,86,86,118,118,2,0,65,65,97,97,2,0,76,76,108,108,2,0,88,88,120,120,2, - 0,70,70,102,102,2,0,77,77,109,109,2,0,71,71,103,103,2,0,75,75,107,107,2, - 0,85,85,117,117,2,0,87,87,119,119,6,0,9,10,13,13,32,32,47,47,91,91,93,93, - 2,0,10,10,13,13,3,0,9,10,13,13,32,32,10,0,9,10,13,13,32,32,44,44,47,47, - 61,61,91,91,93,93,96,96,124,124,2,0,42,42,47,47,1,0,48,57,2,0,65,90,97, - 122,8,0,34,34,78,78,82,82,84,84,92,92,110,110,114,114,116,116,4,0,10,10, - 13,13,34,34,92,92,2,0,43,43,45,45,1,0,96,96,2,0,66,66,98,98,2,0,89,89,121, - 121,11,0,9,10,13,13,32,32,34,35,44,44,47,47,58,58,60,60,62,63,92,92,124, - 124,1427,0,16,1,0,0,0,0,18,1,0,0,0,0,20,1,0,0,0,0,22,1,0,0,0,0,24,1,0,0, - 0,0,26,1,0,0,0,0,28,1,0,0,0,0,30,1,0,0,0,0,32,1,0,0,0,0,34,1,0,0,0,0,36, - 1,0,0,0,0,38,1,0,0,0,0,40,1,0,0,0,0,42,1,0,0,0,0,44,1,0,0,0,0,46,1,0,0, - 0,0,48,1,0,0,0,0,50,1,0,0,0,0,52,1,0,0,0,0,54,1,0,0,0,0,56,1,0,0,0,0,58, - 1,0,0,0,0,60,1,0,0,0,0,62,1,0,0,0,0,66,1,0,0,0,1,68,1,0,0,0,1,70,1,0,0, - 0,1,72,1,0,0,0,1,74,1,0,0,0,1,76,1,0,0,0,2,78,1,0,0,0,2,100,1,0,0,0,2,102, - 1,0,0,0,2,104,1,0,0,0,2,106,1,0,0,0,2,108,1,0,0,0,2,110,1,0,0,0,2,112,1, - 0,0,0,2,114,1,0,0,0,2,116,1,0,0,0,2,118,1,0,0,0,2,120,1,0,0,0,2,122,1,0, - 0,0,2,124,1,0,0,0,2,126,1,0,0,0,2,128,1,0,0,0,2,130,1,0,0,0,2,132,1,0,0, - 0,2,134,1,0,0,0,2,136,1,0,0,0,2,138,1,0,0,0,2,140,1,0,0,0,2,142,1,0,0,0, - 2,144,1,0,0,0,2,146,1,0,0,0,2,148,1,0,0,0,2,150,1,0,0,0,2,152,1,0,0,0,2, - 154,1,0,0,0,2,156,1,0,0,0,2,158,1,0,0,0,2,160,1,0,0,0,2,162,1,0,0,0,2,164, - 1,0,0,0,2,166,1,0,0,0,2,168,1,0,0,0,2,170,1,0,0,0,2,172,1,0,0,0,2,174,1, - 0,0,0,2,176,1,0,0,0,2,178,1,0,0,0,2,180,1,0,0,0,2,184,1,0,0,0,2,186,1,0, - 0,0,2,188,1,0,0,0,2,190,1,0,0,0,3,192,1,0,0,0,3,194,1,0,0,0,3,196,1,0,0, - 0,3,198,1,0,0,0,3,200,1,0,0,0,3,202,1,0,0,0,3,204,1,0,0,0,3,206,1,0,0,0, - 3,208,1,0,0,0,3,210,1,0,0,0,3,212,1,0,0,0,4,214,1,0,0,0,4,216,1,0,0,0,4, - 218,1,0,0,0,4,224,1,0,0,0,4,226,1,0,0,0,4,228,1,0,0,0,4,230,1,0,0,0,5,232, - 1,0,0,0,5,234,1,0,0,0,5,236,1,0,0,0,5,238,1,0,0,0,5,240,1,0,0,0,5,242,1, - 0,0,0,5,244,1,0,0,0,5,246,1,0,0,0,5,248,1,0,0,0,6,250,1,0,0,0,6,252,1,0, - 0,0,6,254,1,0,0,0,6,256,1,0,0,0,6,260,1,0,0,0,6,262,1,0,0,0,6,264,1,0,0, - 0,6,266,1,0,0,0,6,268,1,0,0,0,6,270,1,0,0,0,7,272,1,0,0,0,7,274,1,0,0,0, - 7,276,1,0,0,0,7,278,1,0,0,0,7,280,1,0,0,0,7,282,1,0,0,0,7,284,1,0,0,0,7, - 286,1,0,0,0,7,288,1,0,0,0,7,290,1,0,0,0,8,292,1,0,0,0,8,294,1,0,0,0,8,296, - 1,0,0,0,8,298,1,0,0,0,8,300,1,0,0,0,8,302,1,0,0,0,8,304,1,0,0,0,8,306,1, - 0,0,0,9,308,1,0,0,0,9,310,1,0,0,0,9,312,1,0,0,0,9,314,1,0,0,0,9,316,1,0, - 0,0,9,318,1,0,0,0,9,320,1,0,0,0,10,322,1,0,0,0,10,324,1,0,0,0,10,326,1, - 0,0,0,10,328,1,0,0,0,10,330,1,0,0,0,10,332,1,0,0,0,10,334,1,0,0,0,11,336, - 1,0,0,0,11,338,1,0,0,0,11,340,1,0,0,0,11,342,1,0,0,0,11,344,1,0,0,0,12, - 346,1,0,0,0,12,348,1,0,0,0,12,350,1,0,0,0,12,352,1,0,0,0,12,354,1,0,0,0, - 13,356,1,0,0,0,13,358,1,0,0,0,13,360,1,0,0,0,13,362,1,0,0,0,13,364,1,0, - 0,0,13,366,1,0,0,0,14,368,1,0,0,0,14,370,1,0,0,0,14,372,1,0,0,0,14,374, - 1,0,0,0,14,376,1,0,0,0,15,378,1,0,0,0,15,380,1,0,0,0,15,382,1,0,0,0,15, - 384,1,0,0,0,15,386,1,0,0,0,15,388,1,0,0,0,15,390,1,0,0,0,15,392,1,0,0,0, - 16,394,1,0,0,0,18,404,1,0,0,0,20,411,1,0,0,0,22,420,1,0,0,0,24,427,1,0, - 0,0,26,437,1,0,0,0,28,444,1,0,0,0,30,451,1,0,0,0,32,465,1,0,0,0,34,472, - 1,0,0,0,36,480,1,0,0,0,38,489,1,0,0,0,40,496,1,0,0,0,42,506,1,0,0,0,44, - 518,1,0,0,0,46,527,1,0,0,0,48,533,1,0,0,0,50,540,1,0,0,0,52,547,1,0,0,0, - 54,555,1,0,0,0,56,564,1,0,0,0,58,570,1,0,0,0,60,587,1,0,0,0,62,603,1,0, - 0,0,64,612,1,0,0,0,66,615,1,0,0,0,68,619,1,0,0,0,70,624,1,0,0,0,72,629, - 1,0,0,0,74,633,1,0,0,0,76,637,1,0,0,0,78,641,1,0,0,0,80,645,1,0,0,0,82, - 647,1,0,0,0,84,649,1,0,0,0,86,652,1,0,0,0,88,654,1,0,0,0,90,663,1,0,0,0, - 92,665,1,0,0,0,94,670,1,0,0,0,96,672,1,0,0,0,98,677,1,0,0,0,100,708,1,0, - 0,0,102,711,1,0,0,0,104,757,1,0,0,0,106,759,1,0,0,0,108,762,1,0,0,0,110, - 766,1,0,0,0,112,770,1,0,0,0,114,772,1,0,0,0,116,775,1,0,0,0,118,777,1,0, - 0,0,120,782,1,0,0,0,122,784,1,0,0,0,124,790,1,0,0,0,126,796,1,0,0,0,128, - 801,1,0,0,0,130,803,1,0,0,0,132,806,1,0,0,0,134,809,1,0,0,0,136,814,1,0, - 0,0,138,818,1,0,0,0,140,823,1,0,0,0,142,829,1,0,0,0,144,832,1,0,0,0,146, - 834,1,0,0,0,148,840,1,0,0,0,150,842,1,0,0,0,152,847,1,0,0,0,154,850,1,0, - 0,0,156,853,1,0,0,0,158,856,1,0,0,0,160,858,1,0,0,0,162,861,1,0,0,0,164, - 863,1,0,0,0,166,866,1,0,0,0,168,868,1,0,0,0,170,870,1,0,0,0,172,872,1,0, - 0,0,174,874,1,0,0,0,176,876,1,0,0,0,178,881,1,0,0,0,180,902,1,0,0,0,182, - 904,1,0,0,0,184,912,1,0,0,0,186,914,1,0,0,0,188,918,1,0,0,0,190,922,1,0, - 0,0,192,926,1,0,0,0,194,931,1,0,0,0,196,935,1,0,0,0,198,939,1,0,0,0,200, - 943,1,0,0,0,202,947,1,0,0,0,204,951,1,0,0,0,206,960,1,0,0,0,208,964,1,0, - 0,0,210,968,1,0,0,0,212,972,1,0,0,0,214,976,1,0,0,0,216,981,1,0,0,0,218, - 985,1,0,0,0,220,993,1,0,0,0,222,1014,1,0,0,0,224,1018,1,0,0,0,226,1022, - 1,0,0,0,228,1026,1,0,0,0,230,1030,1,0,0,0,232,1034,1,0,0,0,234,1039,1,0, - 0,0,236,1043,1,0,0,0,238,1047,1,0,0,0,240,1051,1,0,0,0,242,1054,1,0,0,0, - 244,1058,1,0,0,0,246,1062,1,0,0,0,248,1066,1,0,0,0,250,1070,1,0,0,0,252, - 1075,1,0,0,0,254,1080,1,0,0,0,256,1085,1,0,0,0,258,1092,1,0,0,0,260,1101, - 1,0,0,0,262,1108,1,0,0,0,264,1112,1,0,0,0,266,1116,1,0,0,0,268,1120,1,0, - 0,0,270,1124,1,0,0,0,272,1128,1,0,0,0,274,1134,1,0,0,0,276,1138,1,0,0,0, - 278,1142,1,0,0,0,280,1146,1,0,0,0,282,1150,1,0,0,0,284,1154,1,0,0,0,286, - 1158,1,0,0,0,288,1162,1,0,0,0,290,1166,1,0,0,0,292,1170,1,0,0,0,294,1175, - 1,0,0,0,296,1179,1,0,0,0,298,1183,1,0,0,0,300,1188,1,0,0,0,302,1192,1,0, - 0,0,304,1196,1,0,0,0,306,1200,1,0,0,0,308,1204,1,0,0,0,310,1210,1,0,0,0, - 312,1214,1,0,0,0,314,1218,1,0,0,0,316,1222,1,0,0,0,318,1226,1,0,0,0,320, - 1230,1,0,0,0,322,1234,1,0,0,0,324,1239,1,0,0,0,326,1243,1,0,0,0,328,1247, - 1,0,0,0,330,1251,1,0,0,0,332,1255,1,0,0,0,334,1259,1,0,0,0,336,1263,1,0, - 0,0,338,1268,1,0,0,0,340,1273,1,0,0,0,342,1277,1,0,0,0,344,1281,1,0,0,0, - 346,1285,1,0,0,0,348,1290,1,0,0,0,350,1300,1,0,0,0,352,1304,1,0,0,0,354, - 1308,1,0,0,0,356,1312,1,0,0,0,358,1317,1,0,0,0,360,1324,1,0,0,0,362,1328, - 1,0,0,0,364,1332,1,0,0,0,366,1336,1,0,0,0,368,1340,1,0,0,0,370,1345,1,0, - 0,0,372,1351,1,0,0,0,374,1355,1,0,0,0,376,1359,1,0,0,0,378,1363,1,0,0,0, - 380,1369,1,0,0,0,382,1373,1,0,0,0,384,1377,1,0,0,0,386,1381,1,0,0,0,388, - 1387,1,0,0,0,390,1393,1,0,0,0,392,1399,1,0,0,0,394,395,7,0,0,0,395,396, - 7,1,0,0,396,397,7,2,0,0,397,398,7,2,0,0,398,399,7,3,0,0,399,400,7,4,0,0, - 400,401,7,5,0,0,401,402,1,0,0,0,402,403,6,0,0,0,403,17,1,0,0,0,404,405, - 7,0,0,0,405,406,7,6,0,0,406,407,7,7,0,0,407,408,7,8,0,0,408,409,1,0,0,0, - 409,410,6,1,1,0,410,19,1,0,0,0,411,412,7,3,0,0,412,413,7,9,0,0,413,414, - 7,6,0,0,414,415,7,1,0,0,415,416,7,4,0,0,416,417,7,10,0,0,417,418,1,0,0, - 0,418,419,6,2,2,0,419,21,1,0,0,0,420,421,7,3,0,0,421,422,7,11,0,0,422,423, - 7,12,0,0,423,424,7,13,0,0,424,425,1,0,0,0,425,426,6,3,0,0,426,23,1,0,0, - 0,427,428,7,3,0,0,428,429,7,14,0,0,429,430,7,8,0,0,430,431,7,13,0,0,431, - 432,7,12,0,0,432,433,7,1,0,0,433,434,7,9,0,0,434,435,1,0,0,0,435,436,6, - 4,3,0,436,25,1,0,0,0,437,438,7,15,0,0,438,439,7,6,0,0,439,440,7,7,0,0,440, - 441,7,16,0,0,441,442,1,0,0,0,442,443,6,5,4,0,443,27,1,0,0,0,444,445,7,17, - 0,0,445,446,7,6,0,0,446,447,7,7,0,0,447,448,7,18,0,0,448,449,1,0,0,0,449, - 450,6,6,0,0,450,29,1,0,0,0,451,452,7,1,0,0,452,453,7,9,0,0,453,454,7,13, - 0,0,454,455,7,1,0,0,455,456,7,9,0,0,456,457,7,3,0,0,457,458,7,2,0,0,458, - 459,7,5,0,0,459,460,7,12,0,0,460,461,7,5,0,0,461,462,7,2,0,0,462,463,1, - 0,0,0,463,464,6,7,0,0,464,31,1,0,0,0,465,466,7,18,0,0,466,467,7,3,0,0,467, - 468,7,3,0,0,468,469,7,8,0,0,469,470,1,0,0,0,470,471,6,8,1,0,471,33,1,0, - 0,0,472,473,7,13,0,0,473,474,7,1,0,0,474,475,7,16,0,0,475,476,7,1,0,0,476, - 477,7,5,0,0,477,478,1,0,0,0,478,479,6,9,0,0,479,35,1,0,0,0,480,481,7,13, - 0,0,481,482,7,7,0,0,482,483,7,7,0,0,483,484,7,18,0,0,484,485,7,19,0,0,485, - 486,7,8,0,0,486,487,1,0,0,0,487,488,6,10,5,0,488,37,1,0,0,0,489,490,7,16, - 0,0,490,491,7,3,0,0,491,492,7,5,0,0,492,493,7,12,0,0,493,494,1,0,0,0,494, - 495,6,11,6,0,495,39,1,0,0,0,496,497,7,16,0,0,497,498,7,3,0,0,498,499,7, - 5,0,0,499,500,7,6,0,0,500,501,7,1,0,0,501,502,7,4,0,0,502,503,7,2,0,0,503, - 504,1,0,0,0,504,505,6,12,7,0,505,41,1,0,0,0,506,507,7,16,0,0,507,508,7, - 11,0,0,508,509,5,95,0,0,509,510,7,3,0,0,510,511,7,14,0,0,511,512,7,8,0, - 0,512,513,7,12,0,0,513,514,7,9,0,0,514,515,7,0,0,0,515,516,1,0,0,0,516, - 517,6,13,8,0,517,43,1,0,0,0,518,519,7,6,0,0,519,520,7,3,0,0,520,521,7,9, - 0,0,521,522,7,12,0,0,522,523,7,16,0,0,523,524,7,3,0,0,524,525,1,0,0,0,525, - 526,6,14,9,0,526,45,1,0,0,0,527,528,7,6,0,0,528,529,7,7,0,0,529,530,7,20, - 0,0,530,531,1,0,0,0,531,532,6,15,0,0,532,47,1,0,0,0,533,534,7,2,0,0,534, - 535,7,10,0,0,535,536,7,7,0,0,536,537,7,20,0,0,537,538,1,0,0,0,538,539,6, - 16,10,0,539,49,1,0,0,0,540,541,7,2,0,0,541,542,7,7,0,0,542,543,7,6,0,0, - 543,544,7,5,0,0,544,545,1,0,0,0,545,546,6,17,0,0,546,51,1,0,0,0,547,548, - 7,2,0,0,548,549,7,5,0,0,549,550,7,12,0,0,550,551,7,5,0,0,551,552,7,2,0, - 0,552,553,1,0,0,0,553,554,6,18,0,0,554,53,1,0,0,0,555,556,7,20,0,0,556, - 557,7,10,0,0,557,558,7,3,0,0,558,559,7,6,0,0,559,560,7,3,0,0,560,561,1, - 0,0,0,561,562,6,19,0,0,562,55,1,0,0,0,563,565,8,21,0,0,564,563,1,0,0,0, - 565,566,1,0,0,0,566,564,1,0,0,0,566,567,1,0,0,0,567,568,1,0,0,0,568,569, - 6,20,0,0,569,57,1,0,0,0,570,571,5,47,0,0,571,572,5,47,0,0,572,576,1,0,0, - 0,573,575,8,22,0,0,574,573,1,0,0,0,575,578,1,0,0,0,576,574,1,0,0,0,576, - 577,1,0,0,0,577,580,1,0,0,0,578,576,1,0,0,0,579,581,5,13,0,0,580,579,1, - 0,0,0,580,581,1,0,0,0,581,583,1,0,0,0,582,584,5,10,0,0,583,582,1,0,0,0, - 583,584,1,0,0,0,584,585,1,0,0,0,585,586,6,21,11,0,586,59,1,0,0,0,587,588, - 5,47,0,0,588,589,5,42,0,0,589,594,1,0,0,0,590,593,3,60,22,0,591,593,9,0, - 0,0,592,590,1,0,0,0,592,591,1,0,0,0,593,596,1,0,0,0,594,595,1,0,0,0,594, - 592,1,0,0,0,595,597,1,0,0,0,596,594,1,0,0,0,597,598,5,42,0,0,598,599,5, - 47,0,0,599,600,1,0,0,0,600,601,6,22,11,0,601,61,1,0,0,0,602,604,7,23,0, - 0,603,602,1,0,0,0,604,605,1,0,0,0,605,603,1,0,0,0,605,606,1,0,0,0,606,607, - 1,0,0,0,607,608,6,23,11,0,608,63,1,0,0,0,609,613,8,24,0,0,610,611,5,47, - 0,0,611,613,8,25,0,0,612,609,1,0,0,0,612,610,1,0,0,0,613,65,1,0,0,0,614, - 616,3,64,24,0,615,614,1,0,0,0,616,617,1,0,0,0,617,615,1,0,0,0,617,618,1, - 0,0,0,618,67,1,0,0,0,619,620,3,176,80,0,620,621,1,0,0,0,621,622,6,26,12, - 0,622,623,6,26,13,0,623,69,1,0,0,0,624,625,3,78,31,0,625,626,1,0,0,0,626, - 627,6,27,14,0,627,628,6,27,15,0,628,71,1,0,0,0,629,630,3,62,23,0,630,631, - 1,0,0,0,631,632,6,28,11,0,632,73,1,0,0,0,633,634,3,58,21,0,634,635,1,0, - 0,0,635,636,6,29,11,0,636,75,1,0,0,0,637,638,3,60,22,0,638,639,1,0,0,0, - 639,640,6,30,11,0,640,77,1,0,0,0,641,642,5,124,0,0,642,643,1,0,0,0,643, - 644,6,31,15,0,644,79,1,0,0,0,645,646,7,26,0,0,646,81,1,0,0,0,647,648,7, - 27,0,0,648,83,1,0,0,0,649,650,5,92,0,0,650,651,7,28,0,0,651,85,1,0,0,0, - 652,653,8,29,0,0,653,87,1,0,0,0,654,656,7,3,0,0,655,657,7,30,0,0,656,655, - 1,0,0,0,656,657,1,0,0,0,657,659,1,0,0,0,658,660,3,80,32,0,659,658,1,0,0, - 0,660,661,1,0,0,0,661,659,1,0,0,0,661,662,1,0,0,0,662,89,1,0,0,0,663,664, - 5,64,0,0,664,91,1,0,0,0,665,666,5,96,0,0,666,93,1,0,0,0,667,671,8,31,0, - 0,668,669,5,96,0,0,669,671,5,96,0,0,670,667,1,0,0,0,670,668,1,0,0,0,671, - 95,1,0,0,0,672,673,5,95,0,0,673,97,1,0,0,0,674,678,3,82,33,0,675,678,3, - 80,32,0,676,678,3,96,40,0,677,674,1,0,0,0,677,675,1,0,0,0,677,676,1,0,0, - 0,678,99,1,0,0,0,679,684,5,34,0,0,680,683,3,84,34,0,681,683,3,86,35,0,682, - 680,1,0,0,0,682,681,1,0,0,0,683,686,1,0,0,0,684,682,1,0,0,0,684,685,1,0, - 0,0,685,687,1,0,0,0,686,684,1,0,0,0,687,709,5,34,0,0,688,689,5,34,0,0,689, - 690,5,34,0,0,690,691,5,34,0,0,691,695,1,0,0,0,692,694,8,22,0,0,693,692, - 1,0,0,0,694,697,1,0,0,0,695,696,1,0,0,0,695,693,1,0,0,0,696,698,1,0,0,0, - 697,695,1,0,0,0,698,699,5,34,0,0,699,700,5,34,0,0,700,701,5,34,0,0,701, - 703,1,0,0,0,702,704,5,34,0,0,703,702,1,0,0,0,703,704,1,0,0,0,704,706,1, - 0,0,0,705,707,5,34,0,0,706,705,1,0,0,0,706,707,1,0,0,0,707,709,1,0,0,0, - 708,679,1,0,0,0,708,688,1,0,0,0,709,101,1,0,0,0,710,712,3,80,32,0,711,710, - 1,0,0,0,712,713,1,0,0,0,713,711,1,0,0,0,713,714,1,0,0,0,714,103,1,0,0,0, - 715,717,3,80,32,0,716,715,1,0,0,0,717,718,1,0,0,0,718,716,1,0,0,0,718,719, - 1,0,0,0,719,720,1,0,0,0,720,724,3,120,52,0,721,723,3,80,32,0,722,721,1, - 0,0,0,723,726,1,0,0,0,724,722,1,0,0,0,724,725,1,0,0,0,725,758,1,0,0,0,726, - 724,1,0,0,0,727,729,3,120,52,0,728,730,3,80,32,0,729,728,1,0,0,0,730,731, - 1,0,0,0,731,729,1,0,0,0,731,732,1,0,0,0,732,758,1,0,0,0,733,735,3,80,32, - 0,734,733,1,0,0,0,735,736,1,0,0,0,736,734,1,0,0,0,736,737,1,0,0,0,737,745, - 1,0,0,0,738,742,3,120,52,0,739,741,3,80,32,0,740,739,1,0,0,0,741,744,1, - 0,0,0,742,740,1,0,0,0,742,743,1,0,0,0,743,746,1,0,0,0,744,742,1,0,0,0,745, - 738,1,0,0,0,745,746,1,0,0,0,746,747,1,0,0,0,747,748,3,88,36,0,748,758,1, - 0,0,0,749,751,3,120,52,0,750,752,3,80,32,0,751,750,1,0,0,0,752,753,1,0, - 0,0,753,751,1,0,0,0,753,754,1,0,0,0,754,755,1,0,0,0,755,756,3,88,36,0,756, - 758,1,0,0,0,757,716,1,0,0,0,757,727,1,0,0,0,757,734,1,0,0,0,757,749,1,0, - 0,0,758,105,1,0,0,0,759,760,7,32,0,0,760,761,7,33,0,0,761,107,1,0,0,0,762, - 763,7,12,0,0,763,764,7,9,0,0,764,765,7,0,0,0,765,109,1,0,0,0,766,767,7, - 12,0,0,767,768,7,2,0,0,768,769,7,4,0,0,769,111,1,0,0,0,770,771,5,61,0,0, - 771,113,1,0,0,0,772,773,5,58,0,0,773,774,5,58,0,0,774,115,1,0,0,0,775,776, - 5,44,0,0,776,117,1,0,0,0,777,778,7,0,0,0,778,779,7,3,0,0,779,780,7,2,0, - 0,780,781,7,4,0,0,781,119,1,0,0,0,782,783,5,46,0,0,783,121,1,0,0,0,784, - 785,7,15,0,0,785,786,7,12,0,0,786,787,7,13,0,0,787,788,7,2,0,0,788,789, - 7,3,0,0,789,123,1,0,0,0,790,791,7,15,0,0,791,792,7,1,0,0,792,793,7,6,0, - 0,793,794,7,2,0,0,794,795,7,5,0,0,795,125,1,0,0,0,796,797,7,13,0,0,797, - 798,7,12,0,0,798,799,7,2,0,0,799,800,7,5,0,0,800,127,1,0,0,0,801,802,5, - 40,0,0,802,129,1,0,0,0,803,804,7,1,0,0,804,805,7,9,0,0,805,131,1,0,0,0, - 806,807,7,1,0,0,807,808,7,2,0,0,808,133,1,0,0,0,809,810,7,13,0,0,810,811, - 7,1,0,0,811,812,7,18,0,0,812,813,7,3,0,0,813,135,1,0,0,0,814,815,7,9,0, - 0,815,816,7,7,0,0,816,817,7,5,0,0,817,137,1,0,0,0,818,819,7,9,0,0,819,820, - 7,19,0,0,820,821,7,13,0,0,821,822,7,13,0,0,822,139,1,0,0,0,823,824,7,9, - 0,0,824,825,7,19,0,0,825,826,7,13,0,0,826,827,7,13,0,0,827,828,7,2,0,0, - 828,141,1,0,0,0,829,830,7,7,0,0,830,831,7,6,0,0,831,143,1,0,0,0,832,833, - 5,63,0,0,833,145,1,0,0,0,834,835,7,6,0,0,835,836,7,13,0,0,836,837,7,1,0, - 0,837,838,7,18,0,0,838,839,7,3,0,0,839,147,1,0,0,0,840,841,5,41,0,0,841, - 149,1,0,0,0,842,843,7,5,0,0,843,844,7,6,0,0,844,845,7,19,0,0,845,846,7, - 3,0,0,846,151,1,0,0,0,847,848,5,61,0,0,848,849,5,61,0,0,849,153,1,0,0,0, - 850,851,5,61,0,0,851,852,5,126,0,0,852,155,1,0,0,0,853,854,5,33,0,0,854, - 855,5,61,0,0,855,157,1,0,0,0,856,857,5,60,0,0,857,159,1,0,0,0,858,859,5, - 60,0,0,859,860,5,61,0,0,860,161,1,0,0,0,861,862,5,62,0,0,862,163,1,0,0, - 0,863,864,5,62,0,0,864,865,5,61,0,0,865,165,1,0,0,0,866,867,5,43,0,0,867, - 167,1,0,0,0,868,869,5,45,0,0,869,169,1,0,0,0,870,871,5,42,0,0,871,171,1, - 0,0,0,872,873,5,47,0,0,873,173,1,0,0,0,874,875,5,37,0,0,875,175,1,0,0,0, - 876,877,5,91,0,0,877,878,1,0,0,0,878,879,6,80,0,0,879,880,6,80,0,0,880, - 177,1,0,0,0,881,882,5,93,0,0,882,883,1,0,0,0,883,884,6,81,15,0,884,885, - 6,81,15,0,885,179,1,0,0,0,886,890,3,82,33,0,887,889,3,98,41,0,888,887,1, - 0,0,0,889,892,1,0,0,0,890,888,1,0,0,0,890,891,1,0,0,0,891,903,1,0,0,0,892, - 890,1,0,0,0,893,896,3,96,40,0,894,896,3,90,37,0,895,893,1,0,0,0,895,894, - 1,0,0,0,896,898,1,0,0,0,897,899,3,98,41,0,898,897,1,0,0,0,899,900,1,0,0, - 0,900,898,1,0,0,0,900,901,1,0,0,0,901,903,1,0,0,0,902,886,1,0,0,0,902,895, - 1,0,0,0,903,181,1,0,0,0,904,906,3,92,38,0,905,907,3,94,39,0,906,905,1,0, - 0,0,907,908,1,0,0,0,908,906,1,0,0,0,908,909,1,0,0,0,909,910,1,0,0,0,910, - 911,3,92,38,0,911,183,1,0,0,0,912,913,3,182,83,0,913,185,1,0,0,0,914,915, - 3,58,21,0,915,916,1,0,0,0,916,917,6,85,11,0,917,187,1,0,0,0,918,919,3,60, - 22,0,919,920,1,0,0,0,920,921,6,86,11,0,921,189,1,0,0,0,922,923,3,62,23, - 0,923,924,1,0,0,0,924,925,6,87,11,0,925,191,1,0,0,0,926,927,3,78,31,0,927, - 928,1,0,0,0,928,929,6,88,14,0,929,930,6,88,15,0,930,193,1,0,0,0,931,932, - 3,176,80,0,932,933,1,0,0,0,933,934,6,89,12,0,934,195,1,0,0,0,935,936,3, - 178,81,0,936,937,1,0,0,0,937,938,6,90,16,0,938,197,1,0,0,0,939,940,3,116, - 50,0,940,941,1,0,0,0,941,942,6,91,17,0,942,199,1,0,0,0,943,944,3,112,48, - 0,944,945,1,0,0,0,945,946,6,92,18,0,946,201,1,0,0,0,947,948,3,100,42,0, - 948,949,1,0,0,0,949,950,6,93,19,0,950,203,1,0,0,0,951,952,7,16,0,0,952, - 953,7,3,0,0,953,954,7,5,0,0,954,955,7,12,0,0,955,956,7,0,0,0,956,957,7, - 12,0,0,957,958,7,5,0,0,958,959,7,12,0,0,959,205,1,0,0,0,960,961,3,66,25, - 0,961,962,1,0,0,0,962,963,6,95,20,0,963,207,1,0,0,0,964,965,3,58,21,0,965, - 966,1,0,0,0,966,967,6,96,11,0,967,209,1,0,0,0,968,969,3,60,22,0,969,970, - 1,0,0,0,970,971,6,97,11,0,971,211,1,0,0,0,972,973,3,62,23,0,973,974,1,0, - 0,0,974,975,6,98,11,0,975,213,1,0,0,0,976,977,3,78,31,0,977,978,1,0,0,0, - 978,979,6,99,14,0,979,980,6,99,15,0,980,215,1,0,0,0,981,982,3,120,52,0, - 982,983,1,0,0,0,983,984,6,100,21,0,984,217,1,0,0,0,985,986,3,116,50,0,986, - 987,1,0,0,0,987,988,6,101,17,0,988,219,1,0,0,0,989,994,3,82,33,0,990,994, - 3,80,32,0,991,994,3,96,40,0,992,994,3,170,77,0,993,989,1,0,0,0,993,990, - 1,0,0,0,993,991,1,0,0,0,993,992,1,0,0,0,994,221,1,0,0,0,995,998,3,82,33, - 0,996,998,3,170,77,0,997,995,1,0,0,0,997,996,1,0,0,0,998,1002,1,0,0,0,999, - 1001,3,220,102,0,1000,999,1,0,0,0,1001,1004,1,0,0,0,1002,1000,1,0,0,0,1002, - 1003,1,0,0,0,1003,1015,1,0,0,0,1004,1002,1,0,0,0,1005,1008,3,96,40,0,1006, - 1008,3,90,37,0,1007,1005,1,0,0,0,1007,1006,1,0,0,0,1008,1010,1,0,0,0,1009, - 1011,3,220,102,0,1010,1009,1,0,0,0,1011,1012,1,0,0,0,1012,1010,1,0,0,0, - 1012,1013,1,0,0,0,1013,1015,1,0,0,0,1014,997,1,0,0,0,1014,1007,1,0,0,0, - 1015,223,1,0,0,0,1016,1019,3,222,103,0,1017,1019,3,182,83,0,1018,1016,1, - 0,0,0,1018,1017,1,0,0,0,1019,1020,1,0,0,0,1020,1018,1,0,0,0,1020,1021,1, - 0,0,0,1021,225,1,0,0,0,1022,1023,3,58,21,0,1023,1024,1,0,0,0,1024,1025, - 6,105,11,0,1025,227,1,0,0,0,1026,1027,3,60,22,0,1027,1028,1,0,0,0,1028, - 1029,6,106,11,0,1029,229,1,0,0,0,1030,1031,3,62,23,0,1031,1032,1,0,0,0, - 1032,1033,6,107,11,0,1033,231,1,0,0,0,1034,1035,3,78,31,0,1035,1036,1,0, - 0,0,1036,1037,6,108,14,0,1037,1038,6,108,15,0,1038,233,1,0,0,0,1039,1040, - 3,112,48,0,1040,1041,1,0,0,0,1041,1042,6,109,18,0,1042,235,1,0,0,0,1043, - 1044,3,116,50,0,1044,1045,1,0,0,0,1045,1046,6,110,17,0,1046,237,1,0,0,0, - 1047,1048,3,120,52,0,1048,1049,1,0,0,0,1049,1050,6,111,21,0,1050,239,1, - 0,0,0,1051,1052,7,12,0,0,1052,1053,7,2,0,0,1053,241,1,0,0,0,1054,1055,3, - 224,104,0,1055,1056,1,0,0,0,1056,1057,6,113,22,0,1057,243,1,0,0,0,1058, - 1059,3,58,21,0,1059,1060,1,0,0,0,1060,1061,6,114,11,0,1061,245,1,0,0,0, - 1062,1063,3,60,22,0,1063,1064,1,0,0,0,1064,1065,6,115,11,0,1065,247,1,0, - 0,0,1066,1067,3,62,23,0,1067,1068,1,0,0,0,1068,1069,6,116,11,0,1069,249, - 1,0,0,0,1070,1071,3,78,31,0,1071,1072,1,0,0,0,1072,1073,6,117,14,0,1073, - 1074,6,117,15,0,1074,251,1,0,0,0,1075,1076,3,176,80,0,1076,1077,1,0,0,0, - 1077,1078,6,118,12,0,1078,1079,6,118,23,0,1079,253,1,0,0,0,1080,1081,7, - 7,0,0,1081,1082,7,9,0,0,1082,1083,1,0,0,0,1083,1084,6,119,24,0,1084,255, - 1,0,0,0,1085,1086,7,20,0,0,1086,1087,7,1,0,0,1087,1088,7,5,0,0,1088,1089, - 7,10,0,0,1089,1090,1,0,0,0,1090,1091,6,120,24,0,1091,257,1,0,0,0,1092,1093, - 8,34,0,0,1093,259,1,0,0,0,1094,1096,3,258,121,0,1095,1094,1,0,0,0,1096, - 1097,1,0,0,0,1097,1095,1,0,0,0,1097,1098,1,0,0,0,1098,1099,1,0,0,0,1099, - 1100,3,358,171,0,1100,1102,1,0,0,0,1101,1095,1,0,0,0,1101,1102,1,0,0,0, - 1102,1104,1,0,0,0,1103,1105,3,258,121,0,1104,1103,1,0,0,0,1105,1106,1,0, - 0,0,1106,1104,1,0,0,0,1106,1107,1,0,0,0,1107,261,1,0,0,0,1108,1109,3,184, - 84,0,1109,1110,1,0,0,0,1110,1111,6,123,25,0,1111,263,1,0,0,0,1112,1113, - 3,260,122,0,1113,1114,1,0,0,0,1114,1115,6,124,26,0,1115,265,1,0,0,0,1116, - 1117,3,58,21,0,1117,1118,1,0,0,0,1118,1119,6,125,11,0,1119,267,1,0,0,0, - 1120,1121,3,60,22,0,1121,1122,1,0,0,0,1122,1123,6,126,11,0,1123,269,1,0, - 0,0,1124,1125,3,62,23,0,1125,1126,1,0,0,0,1126,1127,6,127,11,0,1127,271, - 1,0,0,0,1128,1129,3,78,31,0,1129,1130,1,0,0,0,1130,1131,6,128,14,0,1131, - 1132,6,128,15,0,1132,1133,6,128,15,0,1133,273,1,0,0,0,1134,1135,3,112,48, - 0,1135,1136,1,0,0,0,1136,1137,6,129,18,0,1137,275,1,0,0,0,1138,1139,3,116, - 50,0,1139,1140,1,0,0,0,1140,1141,6,130,17,0,1141,277,1,0,0,0,1142,1143, - 3,120,52,0,1143,1144,1,0,0,0,1144,1145,6,131,21,0,1145,279,1,0,0,0,1146, - 1147,3,256,120,0,1147,1148,1,0,0,0,1148,1149,6,132,27,0,1149,281,1,0,0, - 0,1150,1151,3,224,104,0,1151,1152,1,0,0,0,1152,1153,6,133,22,0,1153,283, - 1,0,0,0,1154,1155,3,184,84,0,1155,1156,1,0,0,0,1156,1157,6,134,25,0,1157, - 285,1,0,0,0,1158,1159,3,58,21,0,1159,1160,1,0,0,0,1160,1161,6,135,11,0, - 1161,287,1,0,0,0,1162,1163,3,60,22,0,1163,1164,1,0,0,0,1164,1165,6,136, - 11,0,1165,289,1,0,0,0,1166,1167,3,62,23,0,1167,1168,1,0,0,0,1168,1169,6, - 137,11,0,1169,291,1,0,0,0,1170,1171,3,78,31,0,1171,1172,1,0,0,0,1172,1173, - 6,138,14,0,1173,1174,6,138,15,0,1174,293,1,0,0,0,1175,1176,3,116,50,0,1176, - 1177,1,0,0,0,1177,1178,6,139,17,0,1178,295,1,0,0,0,1179,1180,3,120,52,0, - 1180,1181,1,0,0,0,1181,1182,6,140,21,0,1182,297,1,0,0,0,1183,1184,3,254, - 119,0,1184,1185,1,0,0,0,1185,1186,6,141,28,0,1186,1187,6,141,29,0,1187, - 299,1,0,0,0,1188,1189,3,66,25,0,1189,1190,1,0,0,0,1190,1191,6,142,20,0, - 1191,301,1,0,0,0,1192,1193,3,58,21,0,1193,1194,1,0,0,0,1194,1195,6,143, - 11,0,1195,303,1,0,0,0,1196,1197,3,60,22,0,1197,1198,1,0,0,0,1198,1199,6, - 144,11,0,1199,305,1,0,0,0,1200,1201,3,62,23,0,1201,1202,1,0,0,0,1202,1203, - 6,145,11,0,1203,307,1,0,0,0,1204,1205,3,78,31,0,1205,1206,1,0,0,0,1206, - 1207,6,146,14,0,1207,1208,6,146,15,0,1208,1209,6,146,15,0,1209,309,1,0, - 0,0,1210,1211,3,116,50,0,1211,1212,1,0,0,0,1212,1213,6,147,17,0,1213,311, - 1,0,0,0,1214,1215,3,120,52,0,1215,1216,1,0,0,0,1216,1217,6,148,21,0,1217, - 313,1,0,0,0,1218,1219,3,224,104,0,1219,1220,1,0,0,0,1220,1221,6,149,22, - 0,1221,315,1,0,0,0,1222,1223,3,58,21,0,1223,1224,1,0,0,0,1224,1225,6,150, - 11,0,1225,317,1,0,0,0,1226,1227,3,60,22,0,1227,1228,1,0,0,0,1228,1229,6, - 151,11,0,1229,319,1,0,0,0,1230,1231,3,62,23,0,1231,1232,1,0,0,0,1232,1233, - 6,152,11,0,1233,321,1,0,0,0,1234,1235,3,78,31,0,1235,1236,1,0,0,0,1236, - 1237,6,153,14,0,1237,1238,6,153,15,0,1238,323,1,0,0,0,1239,1240,3,120,52, - 0,1240,1241,1,0,0,0,1241,1242,6,154,21,0,1242,325,1,0,0,0,1243,1244,3,184, - 84,0,1244,1245,1,0,0,0,1245,1246,6,155,25,0,1246,327,1,0,0,0,1247,1248, - 3,180,82,0,1248,1249,1,0,0,0,1249,1250,6,156,30,0,1250,329,1,0,0,0,1251, - 1252,3,58,21,0,1252,1253,1,0,0,0,1253,1254,6,157,11,0,1254,331,1,0,0,0, - 1255,1256,3,60,22,0,1256,1257,1,0,0,0,1257,1258,6,158,11,0,1258,333,1,0, - 0,0,1259,1260,3,62,23,0,1260,1261,1,0,0,0,1261,1262,6,159,11,0,1262,335, - 1,0,0,0,1263,1264,3,78,31,0,1264,1265,1,0,0,0,1265,1266,6,160,14,0,1266, - 1267,6,160,15,0,1267,337,1,0,0,0,1268,1269,7,1,0,0,1269,1270,7,9,0,0,1270, - 1271,7,15,0,0,1271,1272,7,7,0,0,1272,339,1,0,0,0,1273,1274,3,58,21,0,1274, - 1275,1,0,0,0,1275,1276,6,162,11,0,1276,341,1,0,0,0,1277,1278,3,60,22,0, - 1278,1279,1,0,0,0,1279,1280,6,163,11,0,1280,343,1,0,0,0,1281,1282,3,62, - 23,0,1282,1283,1,0,0,0,1283,1284,6,164,11,0,1284,345,1,0,0,0,1285,1286, - 3,78,31,0,1286,1287,1,0,0,0,1287,1288,6,165,14,0,1288,1289,6,165,15,0,1289, - 347,1,0,0,0,1290,1291,7,15,0,0,1291,1292,7,19,0,0,1292,1293,7,9,0,0,1293, - 1294,7,4,0,0,1294,1295,7,5,0,0,1295,1296,7,1,0,0,1296,1297,7,7,0,0,1297, - 1298,7,9,0,0,1298,1299,7,2,0,0,1299,349,1,0,0,0,1300,1301,3,58,21,0,1301, - 1302,1,0,0,0,1302,1303,6,167,11,0,1303,351,1,0,0,0,1304,1305,3,60,22,0, - 1305,1306,1,0,0,0,1306,1307,6,168,11,0,1307,353,1,0,0,0,1308,1309,3,62, - 23,0,1309,1310,1,0,0,0,1310,1311,6,169,11,0,1311,355,1,0,0,0,1312,1313, - 3,178,81,0,1313,1314,1,0,0,0,1314,1315,6,170,16,0,1315,1316,6,170,15,0, - 1316,357,1,0,0,0,1317,1318,5,58,0,0,1318,359,1,0,0,0,1319,1325,3,90,37, - 0,1320,1325,3,80,32,0,1321,1325,3,120,52,0,1322,1325,3,82,33,0,1323,1325, - 3,96,40,0,1324,1319,1,0,0,0,1324,1320,1,0,0,0,1324,1321,1,0,0,0,1324,1322, - 1,0,0,0,1324,1323,1,0,0,0,1325,1326,1,0,0,0,1326,1324,1,0,0,0,1326,1327, - 1,0,0,0,1327,361,1,0,0,0,1328,1329,3,58,21,0,1329,1330,1,0,0,0,1330,1331, - 6,173,11,0,1331,363,1,0,0,0,1332,1333,3,60,22,0,1333,1334,1,0,0,0,1334, - 1335,6,174,11,0,1335,365,1,0,0,0,1336,1337,3,62,23,0,1337,1338,1,0,0,0, - 1338,1339,6,175,11,0,1339,367,1,0,0,0,1340,1341,3,78,31,0,1341,1342,1,0, - 0,0,1342,1343,6,176,14,0,1343,1344,6,176,15,0,1344,369,1,0,0,0,1345,1346, - 3,66,25,0,1346,1347,1,0,0,0,1347,1348,6,177,20,0,1348,1349,6,177,15,0,1349, - 1350,6,177,31,0,1350,371,1,0,0,0,1351,1352,3,58,21,0,1352,1353,1,0,0,0, - 1353,1354,6,178,11,0,1354,373,1,0,0,0,1355,1356,3,60,22,0,1356,1357,1,0, - 0,0,1357,1358,6,179,11,0,1358,375,1,0,0,0,1359,1360,3,62,23,0,1360,1361, - 1,0,0,0,1361,1362,6,180,11,0,1362,377,1,0,0,0,1363,1364,3,116,50,0,1364, - 1365,1,0,0,0,1365,1366,6,181,17,0,1366,1367,6,181,15,0,1367,1368,6,181, - 7,0,1368,379,1,0,0,0,1369,1370,3,58,21,0,1370,1371,1,0,0,0,1371,1372,6, - 182,11,0,1372,381,1,0,0,0,1373,1374,3,60,22,0,1374,1375,1,0,0,0,1375,1376, - 6,183,11,0,1376,383,1,0,0,0,1377,1378,3,62,23,0,1378,1379,1,0,0,0,1379, - 1380,6,184,11,0,1380,385,1,0,0,0,1381,1382,3,184,84,0,1382,1383,1,0,0,0, - 1383,1384,6,185,15,0,1384,1385,6,185,0,0,1385,1386,6,185,25,0,1386,387, - 1,0,0,0,1387,1388,3,180,82,0,1388,1389,1,0,0,0,1389,1390,6,186,15,0,1390, - 1391,6,186,0,0,1391,1392,6,186,30,0,1392,389,1,0,0,0,1393,1394,3,106,45, - 0,1394,1395,1,0,0,0,1395,1396,6,187,15,0,1396,1397,6,187,0,0,1397,1398, - 6,187,32,0,1398,391,1,0,0,0,1399,1400,3,78,31,0,1400,1401,1,0,0,0,1401, - 1402,6,188,14,0,1402,1403,6,188,15,0,1403,393,1,0,0,0,62,0,1,2,3,4,5,6, - 7,8,9,10,11,12,13,14,15,566,576,580,583,592,594,605,612,617,656,661,670, - 677,682,684,695,703,706,708,713,718,724,731,736,742,745,753,757,890,895, - 900,902,908,993,997,1002,1007,1012,1014,1018,1020,1097,1101,1106,1324,1326, - 33,5,2,0,5,4,0,5,6,0,5,1,0,5,3,0,5,8,0,5,12,0,5,14,0,5,10,0,5,5,0,5,11, - 0,0,1,0,7,68,0,5,0,0,7,29,0,4,0,0,7,69,0,7,38,0,7,36,0,7,30,0,7,25,0,7, - 40,0,7,79,0,5,13,0,5,7,0,7,71,0,7,89,0,7,88,0,7,87,0,5,9,0,7,70,0,5,15, - 0,7,33,0]; + 2,187,7,187,2,188,7,188,2,189,7,189,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, + 1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3, + 1,3,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5, + 1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7, + 1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9, + 1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,11,1, + 11,1,11,1,11,1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12, + 1,12,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1, + 14,1,14,1,14,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,16, + 1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,18,1, + 18,1,18,1,18,1,18,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,19,1,19,1,19, + 1,20,4,20,567,8,20,11,20,12,20,568,1,20,1,20,1,21,1,21,1,21,1,21,5,21,577, + 8,21,10,21,12,21,580,9,21,1,21,3,21,583,8,21,1,21,3,21,586,8,21,1,21,1, + 21,1,22,1,22,1,22,1,22,1,22,5,22,595,8,22,10,22,12,22,598,9,22,1,22,1,22, + 1,22,1,22,1,22,1,23,4,23,606,8,23,11,23,12,23,607,1,23,1,23,1,24,1,24,1, + 24,3,24,615,8,24,1,25,4,25,618,8,25,11,25,12,25,619,1,26,1,26,1,26,1,26, + 1,26,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,1,29,1,29,1,29,1,29,1, + 30,1,30,1,30,1,30,1,31,1,31,1,31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,34, + 1,35,1,35,1,36,1,36,3,36,659,8,36,1,36,4,36,662,8,36,11,36,12,36,663,1, + 37,1,37,1,38,1,38,1,39,1,39,1,39,3,39,673,8,39,1,40,1,40,1,41,1,41,1,41, + 3,41,680,8,41,1,42,1,42,1,42,5,42,685,8,42,10,42,12,42,688,9,42,1,42,1, + 42,1,42,1,42,1,42,1,42,5,42,696,8,42,10,42,12,42,699,9,42,1,42,1,42,1,42, + 1,42,1,42,3,42,706,8,42,1,42,3,42,709,8,42,3,42,711,8,42,1,43,4,43,714, + 8,43,11,43,12,43,715,1,44,4,44,719,8,44,11,44,12,44,720,1,44,1,44,5,44, + 725,8,44,10,44,12,44,728,9,44,1,44,1,44,4,44,732,8,44,11,44,12,44,733,1, + 44,4,44,737,8,44,11,44,12,44,738,1,44,1,44,5,44,743,8,44,10,44,12,44,746, + 9,44,3,44,748,8,44,1,44,1,44,1,44,1,44,4,44,754,8,44,11,44,12,44,755,1, + 44,1,44,3,44,760,8,44,1,45,1,45,1,45,1,46,1,46,1,46,1,46,1,47,1,47,1,47, + 1,47,1,48,1,48,1,49,1,49,1,49,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1,52,1, + 52,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,54,1,54,1,54,1,55,1,55, + 1,55,1,55,1,55,1,56,1,56,1,57,1,57,1,57,1,58,1,58,1,58,1,59,1,59,1,59,1, + 59,1,59,1,60,1,60,1,60,1,60,1,61,1,61,1,61,1,61,1,61,1,62,1,62,1,62,1,62, + 1,62,1,62,1,63,1,63,1,63,1,64,1,64,1,65,1,65,1,65,1,65,1,65,1,65,1,66,1, + 66,1,67,1,67,1,67,1,67,1,67,1,68,1,68,1,68,1,69,1,69,1,69,1,70,1,70,1,70, + 1,71,1,71,1,72,1,72,1,72,1,73,1,73,1,74,1,74,1,74,1,75,1,75,1,76,1,76,1, + 77,1,77,1,78,1,78,1,79,1,79,1,80,1,80,1,80,5,80,882,8,80,10,80,12,80,885, + 9,80,1,80,1,80,4,80,889,8,80,11,80,12,80,890,3,80,893,8,80,1,81,1,81,1, + 81,1,81,1,81,1,82,1,82,1,82,1,82,1,82,1,83,1,83,5,83,907,8,83,10,83,12, + 83,910,9,83,1,83,1,83,3,83,914,8,83,1,83,4,83,917,8,83,11,83,12,83,918, + 3,83,921,8,83,1,84,1,84,4,84,925,8,84,11,84,12,84,926,1,84,1,84,1,85,1, + 85,1,86,1,86,1,86,1,86,1,87,1,87,1,87,1,87,1,88,1,88,1,88,1,88,1,89,1,89, + 1,89,1,89,1,89,1,90,1,90,1,90,1,90,1,91,1,91,1,91,1,91,1,92,1,92,1,92,1, + 92,1,93,1,93,1,93,1,93,1,94,1,94,1,94,1,94,1,95,1,95,1,95,1,95,1,95,1,95, + 1,95,1,95,1,95,1,96,1,96,1,96,1,96,1,97,1,97,1,97,1,97,1,98,1,98,1,98,1, + 98,1,99,1,99,1,99,1,99,1,100,1,100,1,100,1,100,1,100,1,101,1,101,1,101, + 1,101,1,102,1,102,1,102,1,102,1,103,1,103,1,103,1,103,3,103,1012,8,103, + 1,104,1,104,3,104,1016,8,104,1,104,5,104,1019,8,104,10,104,12,104,1022, + 9,104,1,104,1,104,3,104,1026,8,104,1,104,4,104,1029,8,104,11,104,12,104, + 1030,3,104,1033,8,104,1,105,1,105,4,105,1037,8,105,11,105,12,105,1038,1, + 106,1,106,1,106,1,106,1,107,1,107,1,107,1,107,1,108,1,108,1,108,1,108,1, + 109,1,109,1,109,1,109,1,109,1,110,1,110,1,110,1,110,1,111,1,111,1,111,1, + 111,1,112,1,112,1,112,1,112,1,113,1,113,1,113,1,114,1,114,1,114,1,114,1, + 115,1,115,1,115,1,115,1,116,1,116,1,116,1,116,1,117,1,117,1,117,1,117,1, + 118,1,118,1,118,1,118,1,118,1,119,1,119,1,119,1,119,1,119,1,120,1,120,1, + 120,1,120,1,120,1,121,1,121,1,121,1,121,1,121,1,121,1,121,1,122,1,122,1, + 123,4,123,1114,8,123,11,123,12,123,1115,1,123,1,123,3,123,1120,8,123,1, + 123,4,123,1123,8,123,11,123,12,123,1124,1,124,1,124,1,124,1,124,1,125,1, + 125,1,125,1,125,1,126,1,126,1,126,1,126,1,127,1,127,1,127,1,127,1,128,1, + 128,1,128,1,128,1,129,1,129,1,129,1,129,1,129,1,129,1,130,1,130,1,130,1, + 130,1,131,1,131,1,131,1,131,1,132,1,132,1,132,1,132,1,133,1,133,1,133,1, + 133,1,134,1,134,1,134,1,134,1,135,1,135,1,135,1,135,1,136,1,136,1,136,1, + 136,1,137,1,137,1,137,1,137,1,138,1,138,1,138,1,138,1,139,1,139,1,139,1, + 139,1,139,1,140,1,140,1,140,1,140,1,141,1,141,1,141,1,141,1,142,1,142,1, + 142,1,142,1,142,1,143,1,143,1,143,1,143,1,144,1,144,1,144,1,144,1,145,1, + 145,1,145,1,145,1,146,1,146,1,146,1,146,1,147,1,147,1,147,1,147,1,147,1, + 147,1,148,1,148,1,148,1,148,1,149,1,149,1,149,1,149,1,150,1,150,1,150,1, + 150,1,151,1,151,1,151,1,151,1,152,1,152,1,152,1,152,1,153,1,153,1,153,1, + 153,1,154,1,154,1,154,1,154,1,154,1,155,1,155,1,155,1,155,1,156,1,156,1, + 156,1,156,1,157,1,157,1,157,1,157,1,158,1,158,1,158,1,158,1,159,1,159,1, + 159,1,159,1,160,1,160,1,160,1,160,1,161,1,161,1,161,1,161,1,161,1,162,1, + 162,1,162,1,162,1,162,1,163,1,163,1,163,1,163,1,164,1,164,1,164,1,164,1, + 165,1,165,1,165,1,165,1,166,1,166,1,166,1,166,1,166,1,167,1,167,1,167,1, + 167,1,167,1,167,1,167,1,167,1,167,1,167,1,168,1,168,1,168,1,168,1,169,1, + 169,1,169,1,169,1,170,1,170,1,170,1,170,1,171,1,171,1,171,1,171,1,171,1, + 172,1,172,1,173,1,173,1,173,1,173,1,173,4,173,1343,8,173,11,173,12,173, + 1344,1,174,1,174,1,174,1,174,1,175,1,175,1,175,1,175,1,176,1,176,1,176, + 1,176,1,177,1,177,1,177,1,177,1,177,1,178,1,178,1,178,1,178,1,178,1,178, + 1,179,1,179,1,179,1,179,1,180,1,180,1,180,1,180,1,181,1,181,1,181,1,181, + 1,182,1,182,1,182,1,182,1,182,1,182,1,183,1,183,1,183,1,183,1,184,1,184, + 1,184,1,184,1,185,1,185,1,185,1,185,1,186,1,186,1,186,1,186,1,186,1,186, + 1,187,1,187,1,187,1,187,1,187,1,187,1,188,1,188,1,188,1,188,1,188,1,188, + 1,189,1,189,1,189,1,189,1,189,2,596,697,0,190,16,1,18,2,20,3,22,4,24,5, + 26,6,28,7,30,8,32,9,34,10,36,11,38,12,40,13,42,14,44,15,46,16,48,17,50, + 18,52,19,54,20,56,21,58,22,60,23,62,24,64,0,66,25,68,0,70,0,72,26,74,27, + 76,28,78,29,80,0,82,0,84,0,86,0,88,0,90,0,92,0,94,0,96,0,98,0,100,30,102, + 31,104,32,106,33,108,34,110,35,112,36,114,37,116,38,118,39,120,40,122,41, + 124,42,126,43,128,44,130,45,132,46,134,47,136,48,138,49,140,50,142,51,144, + 52,146,53,148,54,150,55,152,56,154,57,156,58,158,59,160,60,162,61,164,62, + 166,63,168,64,170,65,172,66,174,67,176,68,178,69,180,70,182,71,184,0,186, + 72,188,73,190,74,192,75,194,0,196,0,198,0,200,0,202,0,204,0,206,76,208, + 0,210,77,212,78,214,79,216,0,218,0,220,0,222,0,224,0,226,80,228,81,230, + 82,232,83,234,0,236,0,238,0,240,0,242,84,244,0,246,85,248,86,250,87,252, + 0,254,0,256,88,258,89,260,0,262,90,264,0,266,0,268,91,270,92,272,93,274, + 0,276,0,278,0,280,0,282,0,284,0,286,0,288,94,290,95,292,96,294,0,296,0, + 298,0,300,0,302,0,304,97,306,98,308,99,310,0,312,0,314,0,316,0,318,100, + 320,101,322,102,324,0,326,0,328,0,330,0,332,103,334,104,336,105,338,0,340, + 106,342,107,344,108,346,109,348,0,350,110,352,111,354,112,356,113,358,0, + 360,114,362,115,364,116,366,117,368,118,370,0,372,0,374,119,376,120,378, + 121,380,0,382,122,384,123,386,124,388,0,390,0,392,0,394,0,16,0,1,2,3,4, + 5,6,7,8,9,10,11,12,13,14,15,35,2,0,68,68,100,100,2,0,73,73,105,105,2,0, + 83,83,115,115,2,0,69,69,101,101,2,0,67,67,99,99,2,0,84,84,116,116,2,0,82, + 82,114,114,2,0,79,79,111,111,2,0,80,80,112,112,2,0,78,78,110,110,2,0,72, + 72,104,104,2,0,86,86,118,118,2,0,65,65,97,97,2,0,76,76,108,108,2,0,88,88, + 120,120,2,0,70,70,102,102,2,0,77,77,109,109,2,0,71,71,103,103,2,0,75,75, + 107,107,2,0,85,85,117,117,2,0,87,87,119,119,6,0,9,10,13,13,32,32,47,47, + 91,91,93,93,2,0,10,10,13,13,3,0,9,10,13,13,32,32,10,0,9,10,13,13,32,32, + 44,44,47,47,61,61,91,91,93,93,96,96,124,124,2,0,42,42,47,47,1,0,48,57,2, + 0,65,90,97,122,8,0,34,34,78,78,82,82,84,84,92,92,110,110,114,114,116,116, + 4,0,10,10,13,13,34,34,92,92,2,0,43,43,45,45,1,0,96,96,2,0,66,66,98,98,2, + 0,89,89,121,121,11,0,9,10,13,13,32,32,34,35,44,44,47,47,58,58,60,60,62, + 63,92,92,124,124,1448,0,16,1,0,0,0,0,18,1,0,0,0,0,20,1,0,0,0,0,22,1,0,0, + 0,0,24,1,0,0,0,0,26,1,0,0,0,0,28,1,0,0,0,0,30,1,0,0,0,0,32,1,0,0,0,0,34, + 1,0,0,0,0,36,1,0,0,0,0,38,1,0,0,0,0,40,1,0,0,0,0,42,1,0,0,0,0,44,1,0,0, + 0,0,46,1,0,0,0,0,48,1,0,0,0,0,50,1,0,0,0,0,52,1,0,0,0,0,54,1,0,0,0,0,56, + 1,0,0,0,0,58,1,0,0,0,0,60,1,0,0,0,0,62,1,0,0,0,0,66,1,0,0,0,1,68,1,0,0, + 0,1,70,1,0,0,0,1,72,1,0,0,0,1,74,1,0,0,0,1,76,1,0,0,0,2,78,1,0,0,0,2,100, + 1,0,0,0,2,102,1,0,0,0,2,104,1,0,0,0,2,106,1,0,0,0,2,108,1,0,0,0,2,110,1, + 0,0,0,2,112,1,0,0,0,2,114,1,0,0,0,2,116,1,0,0,0,2,118,1,0,0,0,2,120,1,0, + 0,0,2,122,1,0,0,0,2,124,1,0,0,0,2,126,1,0,0,0,2,128,1,0,0,0,2,130,1,0,0, + 0,2,132,1,0,0,0,2,134,1,0,0,0,2,136,1,0,0,0,2,138,1,0,0,0,2,140,1,0,0,0, + 2,142,1,0,0,0,2,144,1,0,0,0,2,146,1,0,0,0,2,148,1,0,0,0,2,150,1,0,0,0,2, + 152,1,0,0,0,2,154,1,0,0,0,2,156,1,0,0,0,2,158,1,0,0,0,2,160,1,0,0,0,2,162, + 1,0,0,0,2,164,1,0,0,0,2,166,1,0,0,0,2,168,1,0,0,0,2,170,1,0,0,0,2,172,1, + 0,0,0,2,174,1,0,0,0,2,176,1,0,0,0,2,178,1,0,0,0,2,180,1,0,0,0,2,182,1,0, + 0,0,2,186,1,0,0,0,2,188,1,0,0,0,2,190,1,0,0,0,2,192,1,0,0,0,3,194,1,0,0, + 0,3,196,1,0,0,0,3,198,1,0,0,0,3,200,1,0,0,0,3,202,1,0,0,0,3,204,1,0,0,0, + 3,206,1,0,0,0,3,208,1,0,0,0,3,210,1,0,0,0,3,212,1,0,0,0,3,214,1,0,0,0,4, + 216,1,0,0,0,4,218,1,0,0,0,4,220,1,0,0,0,4,226,1,0,0,0,4,228,1,0,0,0,4,230, + 1,0,0,0,4,232,1,0,0,0,5,234,1,0,0,0,5,236,1,0,0,0,5,238,1,0,0,0,5,240,1, + 0,0,0,5,242,1,0,0,0,5,244,1,0,0,0,5,246,1,0,0,0,5,248,1,0,0,0,5,250,1,0, + 0,0,6,252,1,0,0,0,6,254,1,0,0,0,6,256,1,0,0,0,6,258,1,0,0,0,6,262,1,0,0, + 0,6,264,1,0,0,0,6,266,1,0,0,0,6,268,1,0,0,0,6,270,1,0,0,0,6,272,1,0,0,0, + 7,274,1,0,0,0,7,276,1,0,0,0,7,278,1,0,0,0,7,280,1,0,0,0,7,282,1,0,0,0,7, + 284,1,0,0,0,7,286,1,0,0,0,7,288,1,0,0,0,7,290,1,0,0,0,7,292,1,0,0,0,8,294, + 1,0,0,0,8,296,1,0,0,0,8,298,1,0,0,0,8,300,1,0,0,0,8,302,1,0,0,0,8,304,1, + 0,0,0,8,306,1,0,0,0,8,308,1,0,0,0,9,310,1,0,0,0,9,312,1,0,0,0,9,314,1,0, + 0,0,9,316,1,0,0,0,9,318,1,0,0,0,9,320,1,0,0,0,9,322,1,0,0,0,10,324,1,0, + 0,0,10,326,1,0,0,0,10,328,1,0,0,0,10,330,1,0,0,0,10,332,1,0,0,0,10,334, + 1,0,0,0,10,336,1,0,0,0,11,338,1,0,0,0,11,340,1,0,0,0,11,342,1,0,0,0,11, + 344,1,0,0,0,11,346,1,0,0,0,12,348,1,0,0,0,12,350,1,0,0,0,12,352,1,0,0,0, + 12,354,1,0,0,0,12,356,1,0,0,0,13,358,1,0,0,0,13,360,1,0,0,0,13,362,1,0, + 0,0,13,364,1,0,0,0,13,366,1,0,0,0,13,368,1,0,0,0,14,370,1,0,0,0,14,372, + 1,0,0,0,14,374,1,0,0,0,14,376,1,0,0,0,14,378,1,0,0,0,15,380,1,0,0,0,15, + 382,1,0,0,0,15,384,1,0,0,0,15,386,1,0,0,0,15,388,1,0,0,0,15,390,1,0,0,0, + 15,392,1,0,0,0,15,394,1,0,0,0,16,396,1,0,0,0,18,406,1,0,0,0,20,413,1,0, + 0,0,22,422,1,0,0,0,24,429,1,0,0,0,26,439,1,0,0,0,28,446,1,0,0,0,30,453, + 1,0,0,0,32,467,1,0,0,0,34,474,1,0,0,0,36,482,1,0,0,0,38,491,1,0,0,0,40, + 498,1,0,0,0,42,508,1,0,0,0,44,520,1,0,0,0,46,529,1,0,0,0,48,535,1,0,0,0, + 50,542,1,0,0,0,52,549,1,0,0,0,54,557,1,0,0,0,56,566,1,0,0,0,58,572,1,0, + 0,0,60,589,1,0,0,0,62,605,1,0,0,0,64,614,1,0,0,0,66,617,1,0,0,0,68,621, + 1,0,0,0,70,626,1,0,0,0,72,631,1,0,0,0,74,635,1,0,0,0,76,639,1,0,0,0,78, + 643,1,0,0,0,80,647,1,0,0,0,82,649,1,0,0,0,84,651,1,0,0,0,86,654,1,0,0,0, + 88,656,1,0,0,0,90,665,1,0,0,0,92,667,1,0,0,0,94,672,1,0,0,0,96,674,1,0, + 0,0,98,679,1,0,0,0,100,710,1,0,0,0,102,713,1,0,0,0,104,759,1,0,0,0,106, + 761,1,0,0,0,108,764,1,0,0,0,110,768,1,0,0,0,112,772,1,0,0,0,114,774,1,0, + 0,0,116,777,1,0,0,0,118,779,1,0,0,0,120,784,1,0,0,0,122,786,1,0,0,0,124, + 792,1,0,0,0,126,798,1,0,0,0,128,803,1,0,0,0,130,805,1,0,0,0,132,808,1,0, + 0,0,134,811,1,0,0,0,136,816,1,0,0,0,138,820,1,0,0,0,140,825,1,0,0,0,142, + 831,1,0,0,0,144,834,1,0,0,0,146,836,1,0,0,0,148,842,1,0,0,0,150,844,1,0, + 0,0,152,849,1,0,0,0,154,852,1,0,0,0,156,855,1,0,0,0,158,858,1,0,0,0,160, + 860,1,0,0,0,162,863,1,0,0,0,164,865,1,0,0,0,166,868,1,0,0,0,168,870,1,0, + 0,0,170,872,1,0,0,0,172,874,1,0,0,0,174,876,1,0,0,0,176,892,1,0,0,0,178, + 894,1,0,0,0,180,899,1,0,0,0,182,920,1,0,0,0,184,922,1,0,0,0,186,930,1,0, + 0,0,188,932,1,0,0,0,190,936,1,0,0,0,192,940,1,0,0,0,194,944,1,0,0,0,196, + 949,1,0,0,0,198,953,1,0,0,0,200,957,1,0,0,0,202,961,1,0,0,0,204,965,1,0, + 0,0,206,969,1,0,0,0,208,978,1,0,0,0,210,982,1,0,0,0,212,986,1,0,0,0,214, + 990,1,0,0,0,216,994,1,0,0,0,218,999,1,0,0,0,220,1003,1,0,0,0,222,1011,1, + 0,0,0,224,1032,1,0,0,0,226,1036,1,0,0,0,228,1040,1,0,0,0,230,1044,1,0,0, + 0,232,1048,1,0,0,0,234,1052,1,0,0,0,236,1057,1,0,0,0,238,1061,1,0,0,0,240, + 1065,1,0,0,0,242,1069,1,0,0,0,244,1072,1,0,0,0,246,1076,1,0,0,0,248,1080, + 1,0,0,0,250,1084,1,0,0,0,252,1088,1,0,0,0,254,1093,1,0,0,0,256,1098,1,0, + 0,0,258,1103,1,0,0,0,260,1110,1,0,0,0,262,1119,1,0,0,0,264,1126,1,0,0,0, + 266,1130,1,0,0,0,268,1134,1,0,0,0,270,1138,1,0,0,0,272,1142,1,0,0,0,274, + 1146,1,0,0,0,276,1152,1,0,0,0,278,1156,1,0,0,0,280,1160,1,0,0,0,282,1164, + 1,0,0,0,284,1168,1,0,0,0,286,1172,1,0,0,0,288,1176,1,0,0,0,290,1180,1,0, + 0,0,292,1184,1,0,0,0,294,1188,1,0,0,0,296,1193,1,0,0,0,298,1197,1,0,0,0, + 300,1201,1,0,0,0,302,1206,1,0,0,0,304,1210,1,0,0,0,306,1214,1,0,0,0,308, + 1218,1,0,0,0,310,1222,1,0,0,0,312,1228,1,0,0,0,314,1232,1,0,0,0,316,1236, + 1,0,0,0,318,1240,1,0,0,0,320,1244,1,0,0,0,322,1248,1,0,0,0,324,1252,1,0, + 0,0,326,1257,1,0,0,0,328,1261,1,0,0,0,330,1265,1,0,0,0,332,1269,1,0,0,0, + 334,1273,1,0,0,0,336,1277,1,0,0,0,338,1281,1,0,0,0,340,1286,1,0,0,0,342, + 1291,1,0,0,0,344,1295,1,0,0,0,346,1299,1,0,0,0,348,1303,1,0,0,0,350,1308, + 1,0,0,0,352,1318,1,0,0,0,354,1322,1,0,0,0,356,1326,1,0,0,0,358,1330,1,0, + 0,0,360,1335,1,0,0,0,362,1342,1,0,0,0,364,1346,1,0,0,0,366,1350,1,0,0,0, + 368,1354,1,0,0,0,370,1358,1,0,0,0,372,1363,1,0,0,0,374,1369,1,0,0,0,376, + 1373,1,0,0,0,378,1377,1,0,0,0,380,1381,1,0,0,0,382,1387,1,0,0,0,384,1391, + 1,0,0,0,386,1395,1,0,0,0,388,1399,1,0,0,0,390,1405,1,0,0,0,392,1411,1,0, + 0,0,394,1417,1,0,0,0,396,397,7,0,0,0,397,398,7,1,0,0,398,399,7,2,0,0,399, + 400,7,2,0,0,400,401,7,3,0,0,401,402,7,4,0,0,402,403,7,5,0,0,403,404,1,0, + 0,0,404,405,6,0,0,0,405,17,1,0,0,0,406,407,7,0,0,0,407,408,7,6,0,0,408, + 409,7,7,0,0,409,410,7,8,0,0,410,411,1,0,0,0,411,412,6,1,1,0,412,19,1,0, + 0,0,413,414,7,3,0,0,414,415,7,9,0,0,415,416,7,6,0,0,416,417,7,1,0,0,417, + 418,7,4,0,0,418,419,7,10,0,0,419,420,1,0,0,0,420,421,6,2,2,0,421,21,1,0, + 0,0,422,423,7,3,0,0,423,424,7,11,0,0,424,425,7,12,0,0,425,426,7,13,0,0, + 426,427,1,0,0,0,427,428,6,3,0,0,428,23,1,0,0,0,429,430,7,3,0,0,430,431, + 7,14,0,0,431,432,7,8,0,0,432,433,7,13,0,0,433,434,7,12,0,0,434,435,7,1, + 0,0,435,436,7,9,0,0,436,437,1,0,0,0,437,438,6,4,3,0,438,25,1,0,0,0,439, + 440,7,15,0,0,440,441,7,6,0,0,441,442,7,7,0,0,442,443,7,16,0,0,443,444,1, + 0,0,0,444,445,6,5,4,0,445,27,1,0,0,0,446,447,7,17,0,0,447,448,7,6,0,0,448, + 449,7,7,0,0,449,450,7,18,0,0,450,451,1,0,0,0,451,452,6,6,0,0,452,29,1,0, + 0,0,453,454,7,1,0,0,454,455,7,9,0,0,455,456,7,13,0,0,456,457,7,1,0,0,457, + 458,7,9,0,0,458,459,7,3,0,0,459,460,7,2,0,0,460,461,7,5,0,0,461,462,7,12, + 0,0,462,463,7,5,0,0,463,464,7,2,0,0,464,465,1,0,0,0,465,466,6,7,0,0,466, + 31,1,0,0,0,467,468,7,18,0,0,468,469,7,3,0,0,469,470,7,3,0,0,470,471,7,8, + 0,0,471,472,1,0,0,0,472,473,6,8,1,0,473,33,1,0,0,0,474,475,7,13,0,0,475, + 476,7,1,0,0,476,477,7,16,0,0,477,478,7,1,0,0,478,479,7,5,0,0,479,480,1, + 0,0,0,480,481,6,9,0,0,481,35,1,0,0,0,482,483,7,13,0,0,483,484,7,7,0,0,484, + 485,7,7,0,0,485,486,7,18,0,0,486,487,7,19,0,0,487,488,7,8,0,0,488,489,1, + 0,0,0,489,490,6,10,5,0,490,37,1,0,0,0,491,492,7,16,0,0,492,493,7,3,0,0, + 493,494,7,5,0,0,494,495,7,12,0,0,495,496,1,0,0,0,496,497,6,11,6,0,497,39, + 1,0,0,0,498,499,7,16,0,0,499,500,7,3,0,0,500,501,7,5,0,0,501,502,7,6,0, + 0,502,503,7,1,0,0,503,504,7,4,0,0,504,505,7,2,0,0,505,506,1,0,0,0,506,507, + 6,12,7,0,507,41,1,0,0,0,508,509,7,16,0,0,509,510,7,11,0,0,510,511,5,95, + 0,0,511,512,7,3,0,0,512,513,7,14,0,0,513,514,7,8,0,0,514,515,7,12,0,0,515, + 516,7,9,0,0,516,517,7,0,0,0,517,518,1,0,0,0,518,519,6,13,8,0,519,43,1,0, + 0,0,520,521,7,6,0,0,521,522,7,3,0,0,522,523,7,9,0,0,523,524,7,12,0,0,524, + 525,7,16,0,0,525,526,7,3,0,0,526,527,1,0,0,0,527,528,6,14,9,0,528,45,1, + 0,0,0,529,530,7,6,0,0,530,531,7,7,0,0,531,532,7,20,0,0,532,533,1,0,0,0, + 533,534,6,15,0,0,534,47,1,0,0,0,535,536,7,2,0,0,536,537,7,10,0,0,537,538, + 7,7,0,0,538,539,7,20,0,0,539,540,1,0,0,0,540,541,6,16,10,0,541,49,1,0,0, + 0,542,543,7,2,0,0,543,544,7,7,0,0,544,545,7,6,0,0,545,546,7,5,0,0,546,547, + 1,0,0,0,547,548,6,17,0,0,548,51,1,0,0,0,549,550,7,2,0,0,550,551,7,5,0,0, + 551,552,7,12,0,0,552,553,7,5,0,0,553,554,7,2,0,0,554,555,1,0,0,0,555,556, + 6,18,0,0,556,53,1,0,0,0,557,558,7,20,0,0,558,559,7,10,0,0,559,560,7,3,0, + 0,560,561,7,6,0,0,561,562,7,3,0,0,562,563,1,0,0,0,563,564,6,19,0,0,564, + 55,1,0,0,0,565,567,8,21,0,0,566,565,1,0,0,0,567,568,1,0,0,0,568,566,1,0, + 0,0,568,569,1,0,0,0,569,570,1,0,0,0,570,571,6,20,0,0,571,57,1,0,0,0,572, + 573,5,47,0,0,573,574,5,47,0,0,574,578,1,0,0,0,575,577,8,22,0,0,576,575, + 1,0,0,0,577,580,1,0,0,0,578,576,1,0,0,0,578,579,1,0,0,0,579,582,1,0,0,0, + 580,578,1,0,0,0,581,583,5,13,0,0,582,581,1,0,0,0,582,583,1,0,0,0,583,585, + 1,0,0,0,584,586,5,10,0,0,585,584,1,0,0,0,585,586,1,0,0,0,586,587,1,0,0, + 0,587,588,6,21,11,0,588,59,1,0,0,0,589,590,5,47,0,0,590,591,5,42,0,0,591, + 596,1,0,0,0,592,595,3,60,22,0,593,595,9,0,0,0,594,592,1,0,0,0,594,593,1, + 0,0,0,595,598,1,0,0,0,596,597,1,0,0,0,596,594,1,0,0,0,597,599,1,0,0,0,598, + 596,1,0,0,0,599,600,5,42,0,0,600,601,5,47,0,0,601,602,1,0,0,0,602,603,6, + 22,11,0,603,61,1,0,0,0,604,606,7,23,0,0,605,604,1,0,0,0,606,607,1,0,0,0, + 607,605,1,0,0,0,607,608,1,0,0,0,608,609,1,0,0,0,609,610,6,23,11,0,610,63, + 1,0,0,0,611,615,8,24,0,0,612,613,5,47,0,0,613,615,8,25,0,0,614,611,1,0, + 0,0,614,612,1,0,0,0,615,65,1,0,0,0,616,618,3,64,24,0,617,616,1,0,0,0,618, + 619,1,0,0,0,619,617,1,0,0,0,619,620,1,0,0,0,620,67,1,0,0,0,621,622,3,178, + 81,0,622,623,1,0,0,0,623,624,6,26,12,0,624,625,6,26,13,0,625,69,1,0,0,0, + 626,627,3,78,31,0,627,628,1,0,0,0,628,629,6,27,14,0,629,630,6,27,15,0,630, + 71,1,0,0,0,631,632,3,62,23,0,632,633,1,0,0,0,633,634,6,28,11,0,634,73,1, + 0,0,0,635,636,3,58,21,0,636,637,1,0,0,0,637,638,6,29,11,0,638,75,1,0,0, + 0,639,640,3,60,22,0,640,641,1,0,0,0,641,642,6,30,11,0,642,77,1,0,0,0,643, + 644,5,124,0,0,644,645,1,0,0,0,645,646,6,31,15,0,646,79,1,0,0,0,647,648, + 7,26,0,0,648,81,1,0,0,0,649,650,7,27,0,0,650,83,1,0,0,0,651,652,5,92,0, + 0,652,653,7,28,0,0,653,85,1,0,0,0,654,655,8,29,0,0,655,87,1,0,0,0,656,658, + 7,3,0,0,657,659,7,30,0,0,658,657,1,0,0,0,658,659,1,0,0,0,659,661,1,0,0, + 0,660,662,3,80,32,0,661,660,1,0,0,0,662,663,1,0,0,0,663,661,1,0,0,0,663, + 664,1,0,0,0,664,89,1,0,0,0,665,666,5,64,0,0,666,91,1,0,0,0,667,668,5,96, + 0,0,668,93,1,0,0,0,669,673,8,31,0,0,670,671,5,96,0,0,671,673,5,96,0,0,672, + 669,1,0,0,0,672,670,1,0,0,0,673,95,1,0,0,0,674,675,5,95,0,0,675,97,1,0, + 0,0,676,680,3,82,33,0,677,680,3,80,32,0,678,680,3,96,40,0,679,676,1,0,0, + 0,679,677,1,0,0,0,679,678,1,0,0,0,680,99,1,0,0,0,681,686,5,34,0,0,682,685, + 3,84,34,0,683,685,3,86,35,0,684,682,1,0,0,0,684,683,1,0,0,0,685,688,1,0, + 0,0,686,684,1,0,0,0,686,687,1,0,0,0,687,689,1,0,0,0,688,686,1,0,0,0,689, + 711,5,34,0,0,690,691,5,34,0,0,691,692,5,34,0,0,692,693,5,34,0,0,693,697, + 1,0,0,0,694,696,8,22,0,0,695,694,1,0,0,0,696,699,1,0,0,0,697,698,1,0,0, + 0,697,695,1,0,0,0,698,700,1,0,0,0,699,697,1,0,0,0,700,701,5,34,0,0,701, + 702,5,34,0,0,702,703,5,34,0,0,703,705,1,0,0,0,704,706,5,34,0,0,705,704, + 1,0,0,0,705,706,1,0,0,0,706,708,1,0,0,0,707,709,5,34,0,0,708,707,1,0,0, + 0,708,709,1,0,0,0,709,711,1,0,0,0,710,681,1,0,0,0,710,690,1,0,0,0,711,101, + 1,0,0,0,712,714,3,80,32,0,713,712,1,0,0,0,714,715,1,0,0,0,715,713,1,0,0, + 0,715,716,1,0,0,0,716,103,1,0,0,0,717,719,3,80,32,0,718,717,1,0,0,0,719, + 720,1,0,0,0,720,718,1,0,0,0,720,721,1,0,0,0,721,722,1,0,0,0,722,726,3,120, + 52,0,723,725,3,80,32,0,724,723,1,0,0,0,725,728,1,0,0,0,726,724,1,0,0,0, + 726,727,1,0,0,0,727,760,1,0,0,0,728,726,1,0,0,0,729,731,3,120,52,0,730, + 732,3,80,32,0,731,730,1,0,0,0,732,733,1,0,0,0,733,731,1,0,0,0,733,734,1, + 0,0,0,734,760,1,0,0,0,735,737,3,80,32,0,736,735,1,0,0,0,737,738,1,0,0,0, + 738,736,1,0,0,0,738,739,1,0,0,0,739,747,1,0,0,0,740,744,3,120,52,0,741, + 743,3,80,32,0,742,741,1,0,0,0,743,746,1,0,0,0,744,742,1,0,0,0,744,745,1, + 0,0,0,745,748,1,0,0,0,746,744,1,0,0,0,747,740,1,0,0,0,747,748,1,0,0,0,748, + 749,1,0,0,0,749,750,3,88,36,0,750,760,1,0,0,0,751,753,3,120,52,0,752,754, + 3,80,32,0,753,752,1,0,0,0,754,755,1,0,0,0,755,753,1,0,0,0,755,756,1,0,0, + 0,756,757,1,0,0,0,757,758,3,88,36,0,758,760,1,0,0,0,759,718,1,0,0,0,759, + 729,1,0,0,0,759,736,1,0,0,0,759,751,1,0,0,0,760,105,1,0,0,0,761,762,7,32, + 0,0,762,763,7,33,0,0,763,107,1,0,0,0,764,765,7,12,0,0,765,766,7,9,0,0,766, + 767,7,0,0,0,767,109,1,0,0,0,768,769,7,12,0,0,769,770,7,2,0,0,770,771,7, + 4,0,0,771,111,1,0,0,0,772,773,5,61,0,0,773,113,1,0,0,0,774,775,5,58,0,0, + 775,776,5,58,0,0,776,115,1,0,0,0,777,778,5,44,0,0,778,117,1,0,0,0,779,780, + 7,0,0,0,780,781,7,3,0,0,781,782,7,2,0,0,782,783,7,4,0,0,783,119,1,0,0,0, + 784,785,5,46,0,0,785,121,1,0,0,0,786,787,7,15,0,0,787,788,7,12,0,0,788, + 789,7,13,0,0,789,790,7,2,0,0,790,791,7,3,0,0,791,123,1,0,0,0,792,793,7, + 15,0,0,793,794,7,1,0,0,794,795,7,6,0,0,795,796,7,2,0,0,796,797,7,5,0,0, + 797,125,1,0,0,0,798,799,7,13,0,0,799,800,7,12,0,0,800,801,7,2,0,0,801,802, + 7,5,0,0,802,127,1,0,0,0,803,804,5,40,0,0,804,129,1,0,0,0,805,806,7,1,0, + 0,806,807,7,9,0,0,807,131,1,0,0,0,808,809,7,1,0,0,809,810,7,2,0,0,810,133, + 1,0,0,0,811,812,7,13,0,0,812,813,7,1,0,0,813,814,7,18,0,0,814,815,7,3,0, + 0,815,135,1,0,0,0,816,817,7,9,0,0,817,818,7,7,0,0,818,819,7,5,0,0,819,137, + 1,0,0,0,820,821,7,9,0,0,821,822,7,19,0,0,822,823,7,13,0,0,823,824,7,13, + 0,0,824,139,1,0,0,0,825,826,7,9,0,0,826,827,7,19,0,0,827,828,7,13,0,0,828, + 829,7,13,0,0,829,830,7,2,0,0,830,141,1,0,0,0,831,832,7,7,0,0,832,833,7, + 6,0,0,833,143,1,0,0,0,834,835,5,63,0,0,835,145,1,0,0,0,836,837,7,6,0,0, + 837,838,7,13,0,0,838,839,7,1,0,0,839,840,7,18,0,0,840,841,7,3,0,0,841,147, + 1,0,0,0,842,843,5,41,0,0,843,149,1,0,0,0,844,845,7,5,0,0,845,846,7,6,0, + 0,846,847,7,19,0,0,847,848,7,3,0,0,848,151,1,0,0,0,849,850,5,61,0,0,850, + 851,5,61,0,0,851,153,1,0,0,0,852,853,5,61,0,0,853,854,5,126,0,0,854,155, + 1,0,0,0,855,856,5,33,0,0,856,857,5,61,0,0,857,157,1,0,0,0,858,859,5,60, + 0,0,859,159,1,0,0,0,860,861,5,60,0,0,861,862,5,61,0,0,862,161,1,0,0,0,863, + 864,5,62,0,0,864,163,1,0,0,0,865,866,5,62,0,0,866,867,5,61,0,0,867,165, + 1,0,0,0,868,869,5,43,0,0,869,167,1,0,0,0,870,871,5,45,0,0,871,169,1,0,0, + 0,872,873,5,42,0,0,873,171,1,0,0,0,874,875,5,47,0,0,875,173,1,0,0,0,876, + 877,5,37,0,0,877,175,1,0,0,0,878,879,3,144,64,0,879,883,3,82,33,0,880,882, + 3,98,41,0,881,880,1,0,0,0,882,885,1,0,0,0,883,881,1,0,0,0,883,884,1,0,0, + 0,884,893,1,0,0,0,885,883,1,0,0,0,886,888,3,144,64,0,887,889,3,80,32,0, + 888,887,1,0,0,0,889,890,1,0,0,0,890,888,1,0,0,0,890,891,1,0,0,0,891,893, + 1,0,0,0,892,878,1,0,0,0,892,886,1,0,0,0,893,177,1,0,0,0,894,895,5,91,0, + 0,895,896,1,0,0,0,896,897,6,81,0,0,897,898,6,81,0,0,898,179,1,0,0,0,899, + 900,5,93,0,0,900,901,1,0,0,0,901,902,6,82,15,0,902,903,6,82,15,0,903,181, + 1,0,0,0,904,908,3,82,33,0,905,907,3,98,41,0,906,905,1,0,0,0,907,910,1,0, + 0,0,908,906,1,0,0,0,908,909,1,0,0,0,909,921,1,0,0,0,910,908,1,0,0,0,911, + 914,3,96,40,0,912,914,3,90,37,0,913,911,1,0,0,0,913,912,1,0,0,0,914,916, + 1,0,0,0,915,917,3,98,41,0,916,915,1,0,0,0,917,918,1,0,0,0,918,916,1,0,0, + 0,918,919,1,0,0,0,919,921,1,0,0,0,920,904,1,0,0,0,920,913,1,0,0,0,921,183, + 1,0,0,0,922,924,3,92,38,0,923,925,3,94,39,0,924,923,1,0,0,0,925,926,1,0, + 0,0,926,924,1,0,0,0,926,927,1,0,0,0,927,928,1,0,0,0,928,929,3,92,38,0,929, + 185,1,0,0,0,930,931,3,184,84,0,931,187,1,0,0,0,932,933,3,58,21,0,933,934, + 1,0,0,0,934,935,6,86,11,0,935,189,1,0,0,0,936,937,3,60,22,0,937,938,1,0, + 0,0,938,939,6,87,11,0,939,191,1,0,0,0,940,941,3,62,23,0,941,942,1,0,0,0, + 942,943,6,88,11,0,943,193,1,0,0,0,944,945,3,78,31,0,945,946,1,0,0,0,946, + 947,6,89,14,0,947,948,6,89,15,0,948,195,1,0,0,0,949,950,3,178,81,0,950, + 951,1,0,0,0,951,952,6,90,12,0,952,197,1,0,0,0,953,954,3,180,82,0,954,955, + 1,0,0,0,955,956,6,91,16,0,956,199,1,0,0,0,957,958,3,116,50,0,958,959,1, + 0,0,0,959,960,6,92,17,0,960,201,1,0,0,0,961,962,3,112,48,0,962,963,1,0, + 0,0,963,964,6,93,18,0,964,203,1,0,0,0,965,966,3,100,42,0,966,967,1,0,0, + 0,967,968,6,94,19,0,968,205,1,0,0,0,969,970,7,16,0,0,970,971,7,3,0,0,971, + 972,7,5,0,0,972,973,7,12,0,0,973,974,7,0,0,0,974,975,7,12,0,0,975,976,7, + 5,0,0,976,977,7,12,0,0,977,207,1,0,0,0,978,979,3,66,25,0,979,980,1,0,0, + 0,980,981,6,96,20,0,981,209,1,0,0,0,982,983,3,58,21,0,983,984,1,0,0,0,984, + 985,6,97,11,0,985,211,1,0,0,0,986,987,3,60,22,0,987,988,1,0,0,0,988,989, + 6,98,11,0,989,213,1,0,0,0,990,991,3,62,23,0,991,992,1,0,0,0,992,993,6,99, + 11,0,993,215,1,0,0,0,994,995,3,78,31,0,995,996,1,0,0,0,996,997,6,100,14, + 0,997,998,6,100,15,0,998,217,1,0,0,0,999,1000,3,120,52,0,1000,1001,1,0, + 0,0,1001,1002,6,101,21,0,1002,219,1,0,0,0,1003,1004,3,116,50,0,1004,1005, + 1,0,0,0,1005,1006,6,102,17,0,1006,221,1,0,0,0,1007,1012,3,82,33,0,1008, + 1012,3,80,32,0,1009,1012,3,96,40,0,1010,1012,3,170,77,0,1011,1007,1,0,0, + 0,1011,1008,1,0,0,0,1011,1009,1,0,0,0,1011,1010,1,0,0,0,1012,223,1,0,0, + 0,1013,1016,3,82,33,0,1014,1016,3,170,77,0,1015,1013,1,0,0,0,1015,1014, + 1,0,0,0,1016,1020,1,0,0,0,1017,1019,3,222,103,0,1018,1017,1,0,0,0,1019, + 1022,1,0,0,0,1020,1018,1,0,0,0,1020,1021,1,0,0,0,1021,1033,1,0,0,0,1022, + 1020,1,0,0,0,1023,1026,3,96,40,0,1024,1026,3,90,37,0,1025,1023,1,0,0,0, + 1025,1024,1,0,0,0,1026,1028,1,0,0,0,1027,1029,3,222,103,0,1028,1027,1,0, + 0,0,1029,1030,1,0,0,0,1030,1028,1,0,0,0,1030,1031,1,0,0,0,1031,1033,1,0, + 0,0,1032,1015,1,0,0,0,1032,1025,1,0,0,0,1033,225,1,0,0,0,1034,1037,3,224, + 104,0,1035,1037,3,184,84,0,1036,1034,1,0,0,0,1036,1035,1,0,0,0,1037,1038, + 1,0,0,0,1038,1036,1,0,0,0,1038,1039,1,0,0,0,1039,227,1,0,0,0,1040,1041, + 3,58,21,0,1041,1042,1,0,0,0,1042,1043,6,106,11,0,1043,229,1,0,0,0,1044, + 1045,3,60,22,0,1045,1046,1,0,0,0,1046,1047,6,107,11,0,1047,231,1,0,0,0, + 1048,1049,3,62,23,0,1049,1050,1,0,0,0,1050,1051,6,108,11,0,1051,233,1,0, + 0,0,1052,1053,3,78,31,0,1053,1054,1,0,0,0,1054,1055,6,109,14,0,1055,1056, + 6,109,15,0,1056,235,1,0,0,0,1057,1058,3,112,48,0,1058,1059,1,0,0,0,1059, + 1060,6,110,18,0,1060,237,1,0,0,0,1061,1062,3,116,50,0,1062,1063,1,0,0,0, + 1063,1064,6,111,17,0,1064,239,1,0,0,0,1065,1066,3,120,52,0,1066,1067,1, + 0,0,0,1067,1068,6,112,21,0,1068,241,1,0,0,0,1069,1070,7,12,0,0,1070,1071, + 7,2,0,0,1071,243,1,0,0,0,1072,1073,3,226,105,0,1073,1074,1,0,0,0,1074,1075, + 6,114,22,0,1075,245,1,0,0,0,1076,1077,3,58,21,0,1077,1078,1,0,0,0,1078, + 1079,6,115,11,0,1079,247,1,0,0,0,1080,1081,3,60,22,0,1081,1082,1,0,0,0, + 1082,1083,6,116,11,0,1083,249,1,0,0,0,1084,1085,3,62,23,0,1085,1086,1,0, + 0,0,1086,1087,6,117,11,0,1087,251,1,0,0,0,1088,1089,3,78,31,0,1089,1090, + 1,0,0,0,1090,1091,6,118,14,0,1091,1092,6,118,15,0,1092,253,1,0,0,0,1093, + 1094,3,178,81,0,1094,1095,1,0,0,0,1095,1096,6,119,12,0,1096,1097,6,119, + 23,0,1097,255,1,0,0,0,1098,1099,7,7,0,0,1099,1100,7,9,0,0,1100,1101,1,0, + 0,0,1101,1102,6,120,24,0,1102,257,1,0,0,0,1103,1104,7,20,0,0,1104,1105, + 7,1,0,0,1105,1106,7,5,0,0,1106,1107,7,10,0,0,1107,1108,1,0,0,0,1108,1109, + 6,121,24,0,1109,259,1,0,0,0,1110,1111,8,34,0,0,1111,261,1,0,0,0,1112,1114, + 3,260,122,0,1113,1112,1,0,0,0,1114,1115,1,0,0,0,1115,1113,1,0,0,0,1115, + 1116,1,0,0,0,1116,1117,1,0,0,0,1117,1118,3,360,172,0,1118,1120,1,0,0,0, + 1119,1113,1,0,0,0,1119,1120,1,0,0,0,1120,1122,1,0,0,0,1121,1123,3,260,122, + 0,1122,1121,1,0,0,0,1123,1124,1,0,0,0,1124,1122,1,0,0,0,1124,1125,1,0,0, + 0,1125,263,1,0,0,0,1126,1127,3,186,85,0,1127,1128,1,0,0,0,1128,1129,6,124, + 25,0,1129,265,1,0,0,0,1130,1131,3,262,123,0,1131,1132,1,0,0,0,1132,1133, + 6,125,26,0,1133,267,1,0,0,0,1134,1135,3,58,21,0,1135,1136,1,0,0,0,1136, + 1137,6,126,11,0,1137,269,1,0,0,0,1138,1139,3,60,22,0,1139,1140,1,0,0,0, + 1140,1141,6,127,11,0,1141,271,1,0,0,0,1142,1143,3,62,23,0,1143,1144,1,0, + 0,0,1144,1145,6,128,11,0,1145,273,1,0,0,0,1146,1147,3,78,31,0,1147,1148, + 1,0,0,0,1148,1149,6,129,14,0,1149,1150,6,129,15,0,1150,1151,6,129,15,0, + 1151,275,1,0,0,0,1152,1153,3,112,48,0,1153,1154,1,0,0,0,1154,1155,6,130, + 18,0,1155,277,1,0,0,0,1156,1157,3,116,50,0,1157,1158,1,0,0,0,1158,1159, + 6,131,17,0,1159,279,1,0,0,0,1160,1161,3,120,52,0,1161,1162,1,0,0,0,1162, + 1163,6,132,21,0,1163,281,1,0,0,0,1164,1165,3,258,121,0,1165,1166,1,0,0, + 0,1166,1167,6,133,27,0,1167,283,1,0,0,0,1168,1169,3,226,105,0,1169,1170, + 1,0,0,0,1170,1171,6,134,22,0,1171,285,1,0,0,0,1172,1173,3,186,85,0,1173, + 1174,1,0,0,0,1174,1175,6,135,25,0,1175,287,1,0,0,0,1176,1177,3,58,21,0, + 1177,1178,1,0,0,0,1178,1179,6,136,11,0,1179,289,1,0,0,0,1180,1181,3,60, + 22,0,1181,1182,1,0,0,0,1182,1183,6,137,11,0,1183,291,1,0,0,0,1184,1185, + 3,62,23,0,1185,1186,1,0,0,0,1186,1187,6,138,11,0,1187,293,1,0,0,0,1188, + 1189,3,78,31,0,1189,1190,1,0,0,0,1190,1191,6,139,14,0,1191,1192,6,139,15, + 0,1192,295,1,0,0,0,1193,1194,3,116,50,0,1194,1195,1,0,0,0,1195,1196,6,140, + 17,0,1196,297,1,0,0,0,1197,1198,3,120,52,0,1198,1199,1,0,0,0,1199,1200, + 6,141,21,0,1200,299,1,0,0,0,1201,1202,3,256,120,0,1202,1203,1,0,0,0,1203, + 1204,6,142,28,0,1204,1205,6,142,29,0,1205,301,1,0,0,0,1206,1207,3,66,25, + 0,1207,1208,1,0,0,0,1208,1209,6,143,20,0,1209,303,1,0,0,0,1210,1211,3,58, + 21,0,1211,1212,1,0,0,0,1212,1213,6,144,11,0,1213,305,1,0,0,0,1214,1215, + 3,60,22,0,1215,1216,1,0,0,0,1216,1217,6,145,11,0,1217,307,1,0,0,0,1218, + 1219,3,62,23,0,1219,1220,1,0,0,0,1220,1221,6,146,11,0,1221,309,1,0,0,0, + 1222,1223,3,78,31,0,1223,1224,1,0,0,0,1224,1225,6,147,14,0,1225,1226,6, + 147,15,0,1226,1227,6,147,15,0,1227,311,1,0,0,0,1228,1229,3,116,50,0,1229, + 1230,1,0,0,0,1230,1231,6,148,17,0,1231,313,1,0,0,0,1232,1233,3,120,52,0, + 1233,1234,1,0,0,0,1234,1235,6,149,21,0,1235,315,1,0,0,0,1236,1237,3,226, + 105,0,1237,1238,1,0,0,0,1238,1239,6,150,22,0,1239,317,1,0,0,0,1240,1241, + 3,58,21,0,1241,1242,1,0,0,0,1242,1243,6,151,11,0,1243,319,1,0,0,0,1244, + 1245,3,60,22,0,1245,1246,1,0,0,0,1246,1247,6,152,11,0,1247,321,1,0,0,0, + 1248,1249,3,62,23,0,1249,1250,1,0,0,0,1250,1251,6,153,11,0,1251,323,1,0, + 0,0,1252,1253,3,78,31,0,1253,1254,1,0,0,0,1254,1255,6,154,14,0,1255,1256, + 6,154,15,0,1256,325,1,0,0,0,1257,1258,3,120,52,0,1258,1259,1,0,0,0,1259, + 1260,6,155,21,0,1260,327,1,0,0,0,1261,1262,3,186,85,0,1262,1263,1,0,0,0, + 1263,1264,6,156,25,0,1264,329,1,0,0,0,1265,1266,3,182,83,0,1266,1267,1, + 0,0,0,1267,1268,6,157,30,0,1268,331,1,0,0,0,1269,1270,3,58,21,0,1270,1271, + 1,0,0,0,1271,1272,6,158,11,0,1272,333,1,0,0,0,1273,1274,3,60,22,0,1274, + 1275,1,0,0,0,1275,1276,6,159,11,0,1276,335,1,0,0,0,1277,1278,3,62,23,0, + 1278,1279,1,0,0,0,1279,1280,6,160,11,0,1280,337,1,0,0,0,1281,1282,3,78, + 31,0,1282,1283,1,0,0,0,1283,1284,6,161,14,0,1284,1285,6,161,15,0,1285,339, + 1,0,0,0,1286,1287,7,1,0,0,1287,1288,7,9,0,0,1288,1289,7,15,0,0,1289,1290, + 7,7,0,0,1290,341,1,0,0,0,1291,1292,3,58,21,0,1292,1293,1,0,0,0,1293,1294, + 6,163,11,0,1294,343,1,0,0,0,1295,1296,3,60,22,0,1296,1297,1,0,0,0,1297, + 1298,6,164,11,0,1298,345,1,0,0,0,1299,1300,3,62,23,0,1300,1301,1,0,0,0, + 1301,1302,6,165,11,0,1302,347,1,0,0,0,1303,1304,3,78,31,0,1304,1305,1,0, + 0,0,1305,1306,6,166,14,0,1306,1307,6,166,15,0,1307,349,1,0,0,0,1308,1309, + 7,15,0,0,1309,1310,7,19,0,0,1310,1311,7,9,0,0,1311,1312,7,4,0,0,1312,1313, + 7,5,0,0,1313,1314,7,1,0,0,1314,1315,7,7,0,0,1315,1316,7,9,0,0,1316,1317, + 7,2,0,0,1317,351,1,0,0,0,1318,1319,3,58,21,0,1319,1320,1,0,0,0,1320,1321, + 6,168,11,0,1321,353,1,0,0,0,1322,1323,3,60,22,0,1323,1324,1,0,0,0,1324, + 1325,6,169,11,0,1325,355,1,0,0,0,1326,1327,3,62,23,0,1327,1328,1,0,0,0, + 1328,1329,6,170,11,0,1329,357,1,0,0,0,1330,1331,3,180,82,0,1331,1332,1, + 0,0,0,1332,1333,6,171,16,0,1333,1334,6,171,15,0,1334,359,1,0,0,0,1335,1336, + 5,58,0,0,1336,361,1,0,0,0,1337,1343,3,90,37,0,1338,1343,3,80,32,0,1339, + 1343,3,120,52,0,1340,1343,3,82,33,0,1341,1343,3,96,40,0,1342,1337,1,0,0, + 0,1342,1338,1,0,0,0,1342,1339,1,0,0,0,1342,1340,1,0,0,0,1342,1341,1,0,0, + 0,1343,1344,1,0,0,0,1344,1342,1,0,0,0,1344,1345,1,0,0,0,1345,363,1,0,0, + 0,1346,1347,3,58,21,0,1347,1348,1,0,0,0,1348,1349,6,174,11,0,1349,365,1, + 0,0,0,1350,1351,3,60,22,0,1351,1352,1,0,0,0,1352,1353,6,175,11,0,1353,367, + 1,0,0,0,1354,1355,3,62,23,0,1355,1356,1,0,0,0,1356,1357,6,176,11,0,1357, + 369,1,0,0,0,1358,1359,3,78,31,0,1359,1360,1,0,0,0,1360,1361,6,177,14,0, + 1361,1362,6,177,15,0,1362,371,1,0,0,0,1363,1364,3,66,25,0,1364,1365,1,0, + 0,0,1365,1366,6,178,20,0,1366,1367,6,178,15,0,1367,1368,6,178,31,0,1368, + 373,1,0,0,0,1369,1370,3,58,21,0,1370,1371,1,0,0,0,1371,1372,6,179,11,0, + 1372,375,1,0,0,0,1373,1374,3,60,22,0,1374,1375,1,0,0,0,1375,1376,6,180, + 11,0,1376,377,1,0,0,0,1377,1378,3,62,23,0,1378,1379,1,0,0,0,1379,1380,6, + 181,11,0,1380,379,1,0,0,0,1381,1382,3,116,50,0,1382,1383,1,0,0,0,1383,1384, + 6,182,17,0,1384,1385,6,182,15,0,1385,1386,6,182,7,0,1386,381,1,0,0,0,1387, + 1388,3,58,21,0,1388,1389,1,0,0,0,1389,1390,6,183,11,0,1390,383,1,0,0,0, + 1391,1392,3,60,22,0,1392,1393,1,0,0,0,1393,1394,6,184,11,0,1394,385,1,0, + 0,0,1395,1396,3,62,23,0,1396,1397,1,0,0,0,1397,1398,6,185,11,0,1398,387, + 1,0,0,0,1399,1400,3,186,85,0,1400,1401,1,0,0,0,1401,1402,6,186,15,0,1402, + 1403,6,186,0,0,1403,1404,6,186,25,0,1404,389,1,0,0,0,1405,1406,3,182,83, + 0,1406,1407,1,0,0,0,1407,1408,6,187,15,0,1408,1409,6,187,0,0,1409,1410, + 6,187,30,0,1410,391,1,0,0,0,1411,1412,3,106,45,0,1412,1413,1,0,0,0,1413, + 1414,6,188,15,0,1414,1415,6,188,0,0,1415,1416,6,188,32,0,1416,393,1,0,0, + 0,1417,1418,3,78,31,0,1418,1419,1,0,0,0,1419,1420,6,189,14,0,1420,1421, + 6,189,15,0,1421,395,1,0,0,0,65,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,568, + 578,582,585,594,596,607,614,619,658,663,672,679,684,686,697,705,708,710, + 715,720,726,733,738,744,747,755,759,883,890,892,908,913,918,920,926,1011, + 1015,1020,1025,1030,1032,1036,1038,1115,1119,1124,1342,1344,33,5,2,0,5, + 4,0,5,6,0,5,1,0,5,3,0,5,8,0,5,12,0,5,14,0,5,10,0,5,5,0,5,11,0,0,1,0,7,69, + 0,5,0,0,7,29,0,4,0,0,7,70,0,7,38,0,7,36,0,7,30,0,7,25,0,7,40,0,7,80,0,5, + 13,0,5,7,0,7,72,0,7,90,0,7,89,0,7,88,0,5,9,0,7,71,0,5,15,0,7,33,0]; private static __ATN: ATN; public static get _ATN(): ATN { diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.g4 b/packages/kbn-esql-ast/src/antlr/esql_parser.g4 index d4f9de9dccd9e..59c9ee6ca5770 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.g4 +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.g4 @@ -179,13 +179,18 @@ constant | decimalValue #decimalLiteral | integerValue #integerLiteral | booleanValue #booleanLiteral - | PARAM #inputParam + | params #inputParams | string #stringLiteral | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET #numericArrayLiteral | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET #booleanArrayLiteral | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET #stringArrayLiteral ; +params + : PARAM #inputParam + | NAMED_OR_POSITIONAL_PARAM #inputNamedOrPositionalParam + ; + limitCommand : LIMIT INTEGER_LITERAL ; diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.interp b/packages/kbn-esql-ast/src/antlr/esql_parser.interp index 76663717c5624..5900020590110 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.interp +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.interp @@ -68,6 +68,7 @@ null '/' '%' null +null ']' null null @@ -193,6 +194,7 @@ MINUS ASTERISK SLASH PERCENT +NAMED_OR_POSITIONAL_PARAM OPENING_BRACKET CLOSING_BRACKET UNQUOTED_IDENTIFIER @@ -281,6 +283,7 @@ qualifiedNamePatterns identifier identifierPattern constant +params limitCommand sortCommand orderExpression @@ -309,4 +312,4 @@ lookupCommand atn: -[4, 1, 123, 548, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 120, 8, 1, 10, 1, 12, 1, 123, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 131, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 147, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 159, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 166, 8, 5, 10, 5, 12, 5, 169, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 176, 8, 5, 1, 5, 1, 5, 3, 5, 180, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 188, 8, 5, 10, 5, 12, 5, 191, 9, 5, 1, 6, 1, 6, 3, 6, 195, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 202, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 207, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 214, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 220, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 228, 8, 8, 10, 8, 12, 8, 231, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 241, 8, 9, 1, 9, 1, 9, 1, 9, 5, 9, 246, 8, 9, 10, 9, 12, 9, 249, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 257, 8, 10, 10, 10, 12, 10, 260, 9, 10, 3, 10, 262, 8, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 274, 8, 13, 10, 13, 12, 13, 277, 9, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 284, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 290, 8, 15, 10, 15, 12, 15, 293, 9, 15, 1, 15, 3, 15, 296, 8, 15, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 302, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 308, 8, 18, 10, 18, 12, 18, 311, 9, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 321, 8, 20, 10, 20, 12, 20, 324, 9, 20, 1, 20, 3, 20, 327, 8, 20, 1, 20, 1, 20, 3, 20, 331, 8, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 3, 22, 338, 8, 22, 1, 22, 1, 22, 3, 22, 342, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 348, 8, 23, 1, 24, 1, 24, 1, 24, 5, 24, 353, 8, 24, 10, 24, 12, 24, 356, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 361, 8, 25, 10, 25, 12, 25, 364, 9, 25, 1, 26, 1, 26, 1, 26, 5, 26, 369, 8, 26, 10, 26, 12, 26, 372, 9, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 391, 8, 29, 10, 29, 12, 29, 394, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 402, 8, 29, 10, 29, 12, 29, 405, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 413, 8, 29, 10, 29, 12, 29, 416, 9, 29, 1, 29, 1, 29, 3, 29, 420, 8, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 429, 8, 31, 10, 31, 12, 31, 432, 9, 31, 1, 32, 1, 32, 3, 32, 436, 8, 32, 1, 32, 1, 32, 3, 32, 440, 8, 32, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 452, 8, 35, 10, 35, 12, 35, 455, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 465, 8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 5, 40, 477, 8, 40, 10, 40, 12, 40, 480, 9, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 1, 43, 3, 43, 490, 8, 43, 1, 44, 3, 44, 493, 8, 44, 1, 44, 1, 44, 1, 45, 3, 45, 498, 8, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 3, 52, 523, 8, 52, 1, 52, 1, 52, 1, 52, 1, 52, 5, 52, 529, 8, 52, 10, 52, 12, 52, 532, 9, 52, 3, 52, 534, 8, 52, 1, 53, 1, 53, 1, 53, 3, 53, 539, 8, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 0, 4, 2, 10, 16, 18, 55, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 0, 7, 1, 0, 63, 64, 1, 0, 65, 67, 1, 0, 70, 71, 2, 0, 35, 35, 39, 39, 1, 0, 42, 43, 2, 0, 41, 41, 55, 55, 2, 0, 56, 56, 58, 62, 574, 0, 110, 1, 0, 0, 0, 2, 113, 1, 0, 0, 0, 4, 130, 1, 0, 0, 0, 6, 146, 1, 0, 0, 0, 8, 148, 1, 0, 0, 0, 10, 179, 1, 0, 0, 0, 12, 206, 1, 0, 0, 0, 14, 213, 1, 0, 0, 0, 16, 219, 1, 0, 0, 0, 18, 240, 1, 0, 0, 0, 20, 250, 1, 0, 0, 0, 22, 265, 1, 0, 0, 0, 24, 267, 1, 0, 0, 0, 26, 270, 1, 0, 0, 0, 28, 283, 1, 0, 0, 0, 30, 285, 1, 0, 0, 0, 32, 297, 1, 0, 0, 0, 34, 301, 1, 0, 0, 0, 36, 303, 1, 0, 0, 0, 38, 312, 1, 0, 0, 0, 40, 316, 1, 0, 0, 0, 42, 332, 1, 0, 0, 0, 44, 335, 1, 0, 0, 0, 46, 343, 1, 0, 0, 0, 48, 349, 1, 0, 0, 0, 50, 357, 1, 0, 0, 0, 52, 365, 1, 0, 0, 0, 54, 373, 1, 0, 0, 0, 56, 375, 1, 0, 0, 0, 58, 419, 1, 0, 0, 0, 60, 421, 1, 0, 0, 0, 62, 424, 1, 0, 0, 0, 64, 433, 1, 0, 0, 0, 66, 441, 1, 0, 0, 0, 68, 444, 1, 0, 0, 0, 70, 447, 1, 0, 0, 0, 72, 456, 1, 0, 0, 0, 74, 460, 1, 0, 0, 0, 76, 466, 1, 0, 0, 0, 78, 470, 1, 0, 0, 0, 80, 473, 1, 0, 0, 0, 82, 481, 1, 0, 0, 0, 84, 485, 1, 0, 0, 0, 86, 489, 1, 0, 0, 0, 88, 492, 1, 0, 0, 0, 90, 497, 1, 0, 0, 0, 92, 501, 1, 0, 0, 0, 94, 503, 1, 0, 0, 0, 96, 505, 1, 0, 0, 0, 98, 508, 1, 0, 0, 0, 100, 512, 1, 0, 0, 0, 102, 515, 1, 0, 0, 0, 104, 518, 1, 0, 0, 0, 106, 538, 1, 0, 0, 0, 108, 542, 1, 0, 0, 0, 110, 111, 3, 2, 1, 0, 111, 112, 5, 0, 0, 1, 112, 1, 1, 0, 0, 0, 113, 114, 6, 1, -1, 0, 114, 115, 3, 4, 2, 0, 115, 121, 1, 0, 0, 0, 116, 117, 10, 1, 0, 0, 117, 118, 5, 29, 0, 0, 118, 120, 3, 6, 3, 0, 119, 116, 1, 0, 0, 0, 120, 123, 1, 0, 0, 0, 121, 119, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 3, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 124, 131, 3, 96, 48, 0, 125, 131, 3, 30, 15, 0, 126, 131, 3, 24, 12, 0, 127, 131, 3, 40, 20, 0, 128, 131, 3, 100, 50, 0, 129, 131, 3, 102, 51, 0, 130, 124, 1, 0, 0, 0, 130, 125, 1, 0, 0, 0, 130, 126, 1, 0, 0, 0, 130, 127, 1, 0, 0, 0, 130, 128, 1, 0, 0, 0, 130, 129, 1, 0, 0, 0, 131, 5, 1, 0, 0, 0, 132, 147, 3, 42, 21, 0, 133, 147, 3, 46, 23, 0, 134, 147, 3, 60, 30, 0, 135, 147, 3, 108, 54, 0, 136, 147, 3, 66, 33, 0, 137, 147, 3, 62, 31, 0, 138, 147, 3, 44, 22, 0, 139, 147, 3, 8, 4, 0, 140, 147, 3, 68, 34, 0, 141, 147, 3, 70, 35, 0, 142, 147, 3, 74, 37, 0, 143, 147, 3, 76, 38, 0, 144, 147, 3, 104, 52, 0, 145, 147, 3, 78, 39, 0, 146, 132, 1, 0, 0, 0, 146, 133, 1, 0, 0, 0, 146, 134, 1, 0, 0, 0, 146, 135, 1, 0, 0, 0, 146, 136, 1, 0, 0, 0, 146, 137, 1, 0, 0, 0, 146, 138, 1, 0, 0, 0, 146, 139, 1, 0, 0, 0, 146, 140, 1, 0, 0, 0, 146, 141, 1, 0, 0, 0, 146, 142, 1, 0, 0, 0, 146, 143, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 146, 145, 1, 0, 0, 0, 147, 7, 1, 0, 0, 0, 148, 149, 5, 20, 0, 0, 149, 150, 3, 10, 5, 0, 150, 9, 1, 0, 0, 0, 151, 152, 6, 5, -1, 0, 152, 153, 5, 48, 0, 0, 153, 180, 3, 10, 5, 7, 154, 180, 3, 14, 7, 0, 155, 180, 3, 12, 6, 0, 156, 158, 3, 14, 7, 0, 157, 159, 5, 48, 0, 0, 158, 157, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 161, 5, 45, 0, 0, 161, 162, 5, 44, 0, 0, 162, 167, 3, 14, 7, 0, 163, 164, 5, 38, 0, 0, 164, 166, 3, 14, 7, 0, 165, 163, 1, 0, 0, 0, 166, 169, 1, 0, 0, 0, 167, 165, 1, 0, 0, 0, 167, 168, 1, 0, 0, 0, 168, 170, 1, 0, 0, 0, 169, 167, 1, 0, 0, 0, 170, 171, 5, 54, 0, 0, 171, 180, 1, 0, 0, 0, 172, 173, 3, 14, 7, 0, 173, 175, 5, 46, 0, 0, 174, 176, 5, 48, 0, 0, 175, 174, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 178, 5, 49, 0, 0, 178, 180, 1, 0, 0, 0, 179, 151, 1, 0, 0, 0, 179, 154, 1, 0, 0, 0, 179, 155, 1, 0, 0, 0, 179, 156, 1, 0, 0, 0, 179, 172, 1, 0, 0, 0, 180, 189, 1, 0, 0, 0, 181, 182, 10, 4, 0, 0, 182, 183, 5, 34, 0, 0, 183, 188, 3, 10, 5, 5, 184, 185, 10, 3, 0, 0, 185, 186, 5, 51, 0, 0, 186, 188, 3, 10, 5, 4, 187, 181, 1, 0, 0, 0, 187, 184, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 11, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 194, 3, 14, 7, 0, 193, 195, 5, 48, 0, 0, 194, 193, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 197, 5, 47, 0, 0, 197, 198, 3, 92, 46, 0, 198, 207, 1, 0, 0, 0, 199, 201, 3, 14, 7, 0, 200, 202, 5, 48, 0, 0, 201, 200, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 204, 5, 53, 0, 0, 204, 205, 3, 92, 46, 0, 205, 207, 1, 0, 0, 0, 206, 192, 1, 0, 0, 0, 206, 199, 1, 0, 0, 0, 207, 13, 1, 0, 0, 0, 208, 214, 3, 16, 8, 0, 209, 210, 3, 16, 8, 0, 210, 211, 3, 94, 47, 0, 211, 212, 3, 16, 8, 0, 212, 214, 1, 0, 0, 0, 213, 208, 1, 0, 0, 0, 213, 209, 1, 0, 0, 0, 214, 15, 1, 0, 0, 0, 215, 216, 6, 8, -1, 0, 216, 220, 3, 18, 9, 0, 217, 218, 7, 0, 0, 0, 218, 220, 3, 16, 8, 3, 219, 215, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0, 220, 229, 1, 0, 0, 0, 221, 222, 10, 2, 0, 0, 222, 223, 7, 1, 0, 0, 223, 228, 3, 16, 8, 3, 224, 225, 10, 1, 0, 0, 225, 226, 7, 0, 0, 0, 226, 228, 3, 16, 8, 2, 227, 221, 1, 0, 0, 0, 227, 224, 1, 0, 0, 0, 228, 231, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 17, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 232, 233, 6, 9, -1, 0, 233, 241, 3, 58, 29, 0, 234, 241, 3, 48, 24, 0, 235, 241, 3, 20, 10, 0, 236, 237, 5, 44, 0, 0, 237, 238, 3, 10, 5, 0, 238, 239, 5, 54, 0, 0, 239, 241, 1, 0, 0, 0, 240, 232, 1, 0, 0, 0, 240, 234, 1, 0, 0, 0, 240, 235, 1, 0, 0, 0, 240, 236, 1, 0, 0, 0, 241, 247, 1, 0, 0, 0, 242, 243, 10, 1, 0, 0, 243, 244, 5, 37, 0, 0, 244, 246, 3, 22, 11, 0, 245, 242, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 19, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 251, 3, 54, 27, 0, 251, 261, 5, 44, 0, 0, 252, 262, 5, 65, 0, 0, 253, 258, 3, 10, 5, 0, 254, 255, 5, 38, 0, 0, 255, 257, 3, 10, 5, 0, 256, 254, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 262, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 252, 1, 0, 0, 0, 261, 253, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263, 1, 0, 0, 0, 263, 264, 5, 54, 0, 0, 264, 21, 1, 0, 0, 0, 265, 266, 3, 54, 27, 0, 266, 23, 1, 0, 0, 0, 267, 268, 5, 16, 0, 0, 268, 269, 3, 26, 13, 0, 269, 25, 1, 0, 0, 0, 270, 275, 3, 28, 14, 0, 271, 272, 5, 38, 0, 0, 272, 274, 3, 28, 14, 0, 273, 271, 1, 0, 0, 0, 274, 277, 1, 0, 0, 0, 275, 273, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 27, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 278, 284, 3, 10, 5, 0, 279, 280, 3, 48, 24, 0, 280, 281, 5, 36, 0, 0, 281, 282, 3, 10, 5, 0, 282, 284, 1, 0, 0, 0, 283, 278, 1, 0, 0, 0, 283, 279, 1, 0, 0, 0, 284, 29, 1, 0, 0, 0, 285, 286, 5, 6, 0, 0, 286, 291, 3, 32, 16, 0, 287, 288, 5, 38, 0, 0, 288, 290, 3, 32, 16, 0, 289, 287, 1, 0, 0, 0, 290, 293, 1, 0, 0, 0, 291, 289, 1, 0, 0, 0, 291, 292, 1, 0, 0, 0, 292, 295, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, 294, 296, 3, 34, 17, 0, 295, 294, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 31, 1, 0, 0, 0, 297, 298, 5, 25, 0, 0, 298, 33, 1, 0, 0, 0, 299, 302, 3, 36, 18, 0, 300, 302, 3, 38, 19, 0, 301, 299, 1, 0, 0, 0, 301, 300, 1, 0, 0, 0, 302, 35, 1, 0, 0, 0, 303, 304, 5, 75, 0, 0, 304, 309, 3, 32, 16, 0, 305, 306, 5, 38, 0, 0, 306, 308, 3, 32, 16, 0, 307, 305, 1, 0, 0, 0, 308, 311, 1, 0, 0, 0, 309, 307, 1, 0, 0, 0, 309, 310, 1, 0, 0, 0, 310, 37, 1, 0, 0, 0, 311, 309, 1, 0, 0, 0, 312, 313, 5, 68, 0, 0, 313, 314, 3, 36, 18, 0, 314, 315, 5, 69, 0, 0, 315, 39, 1, 0, 0, 0, 316, 317, 5, 13, 0, 0, 317, 322, 3, 32, 16, 0, 318, 319, 5, 38, 0, 0, 319, 321, 3, 32, 16, 0, 320, 318, 1, 0, 0, 0, 321, 324, 1, 0, 0, 0, 322, 320, 1, 0, 0, 0, 322, 323, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 325, 327, 3, 26, 13, 0, 326, 325, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 329, 5, 33, 0, 0, 329, 331, 3, 26, 13, 0, 330, 328, 1, 0, 0, 0, 330, 331, 1, 0, 0, 0, 331, 41, 1, 0, 0, 0, 332, 333, 5, 4, 0, 0, 333, 334, 3, 26, 13, 0, 334, 43, 1, 0, 0, 0, 335, 337, 5, 19, 0, 0, 336, 338, 3, 26, 13, 0, 337, 336, 1, 0, 0, 0, 337, 338, 1, 0, 0, 0, 338, 341, 1, 0, 0, 0, 339, 340, 5, 33, 0, 0, 340, 342, 3, 26, 13, 0, 341, 339, 1, 0, 0, 0, 341, 342, 1, 0, 0, 0, 342, 45, 1, 0, 0, 0, 343, 344, 5, 8, 0, 0, 344, 347, 3, 26, 13, 0, 345, 346, 5, 33, 0, 0, 346, 348, 3, 26, 13, 0, 347, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 47, 1, 0, 0, 0, 349, 354, 3, 54, 27, 0, 350, 351, 5, 40, 0, 0, 351, 353, 3, 54, 27, 0, 352, 350, 1, 0, 0, 0, 353, 356, 1, 0, 0, 0, 354, 352, 1, 0, 0, 0, 354, 355, 1, 0, 0, 0, 355, 49, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 357, 362, 3, 56, 28, 0, 358, 359, 5, 40, 0, 0, 359, 361, 3, 56, 28, 0, 360, 358, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 51, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 370, 3, 50, 25, 0, 366, 367, 5, 38, 0, 0, 367, 369, 3, 50, 25, 0, 368, 366, 1, 0, 0, 0, 369, 372, 1, 0, 0, 0, 370, 368, 1, 0, 0, 0, 370, 371, 1, 0, 0, 0, 371, 53, 1, 0, 0, 0, 372, 370, 1, 0, 0, 0, 373, 374, 7, 2, 0, 0, 374, 55, 1, 0, 0, 0, 375, 376, 5, 79, 0, 0, 376, 57, 1, 0, 0, 0, 377, 420, 5, 49, 0, 0, 378, 379, 3, 90, 45, 0, 379, 380, 5, 70, 0, 0, 380, 420, 1, 0, 0, 0, 381, 420, 3, 88, 44, 0, 382, 420, 3, 90, 45, 0, 383, 420, 3, 84, 42, 0, 384, 420, 5, 52, 0, 0, 385, 420, 3, 92, 46, 0, 386, 387, 5, 68, 0, 0, 387, 392, 3, 86, 43, 0, 388, 389, 5, 38, 0, 0, 389, 391, 3, 86, 43, 0, 390, 388, 1, 0, 0, 0, 391, 394, 1, 0, 0, 0, 392, 390, 1, 0, 0, 0, 392, 393, 1, 0, 0, 0, 393, 395, 1, 0, 0, 0, 394, 392, 1, 0, 0, 0, 395, 396, 5, 69, 0, 0, 396, 420, 1, 0, 0, 0, 397, 398, 5, 68, 0, 0, 398, 403, 3, 84, 42, 0, 399, 400, 5, 38, 0, 0, 400, 402, 3, 84, 42, 0, 401, 399, 1, 0, 0, 0, 402, 405, 1, 0, 0, 0, 403, 401, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 406, 1, 0, 0, 0, 405, 403, 1, 0, 0, 0, 406, 407, 5, 69, 0, 0, 407, 420, 1, 0, 0, 0, 408, 409, 5, 68, 0, 0, 409, 414, 3, 92, 46, 0, 410, 411, 5, 38, 0, 0, 411, 413, 3, 92, 46, 0, 412, 410, 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 414, 415, 1, 0, 0, 0, 415, 417, 1, 0, 0, 0, 416, 414, 1, 0, 0, 0, 417, 418, 5, 69, 0, 0, 418, 420, 1, 0, 0, 0, 419, 377, 1, 0, 0, 0, 419, 378, 1, 0, 0, 0, 419, 381, 1, 0, 0, 0, 419, 382, 1, 0, 0, 0, 419, 383, 1, 0, 0, 0, 419, 384, 1, 0, 0, 0, 419, 385, 1, 0, 0, 0, 419, 386, 1, 0, 0, 0, 419, 397, 1, 0, 0, 0, 419, 408, 1, 0, 0, 0, 420, 59, 1, 0, 0, 0, 421, 422, 5, 10, 0, 0, 422, 423, 5, 31, 0, 0, 423, 61, 1, 0, 0, 0, 424, 425, 5, 18, 0, 0, 425, 430, 3, 64, 32, 0, 426, 427, 5, 38, 0, 0, 427, 429, 3, 64, 32, 0, 428, 426, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 430, 431, 1, 0, 0, 0, 431, 63, 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 433, 435, 3, 10, 5, 0, 434, 436, 7, 3, 0, 0, 435, 434, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 439, 1, 0, 0, 0, 437, 438, 5, 50, 0, 0, 438, 440, 7, 4, 0, 0, 439, 437, 1, 0, 0, 0, 439, 440, 1, 0, 0, 0, 440, 65, 1, 0, 0, 0, 441, 442, 5, 9, 0, 0, 442, 443, 3, 52, 26, 0, 443, 67, 1, 0, 0, 0, 444, 445, 5, 2, 0, 0, 445, 446, 3, 52, 26, 0, 446, 69, 1, 0, 0, 0, 447, 448, 5, 15, 0, 0, 448, 453, 3, 72, 36, 0, 449, 450, 5, 38, 0, 0, 450, 452, 3, 72, 36, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 71, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 457, 3, 50, 25, 0, 457, 458, 5, 83, 0, 0, 458, 459, 3, 50, 25, 0, 459, 73, 1, 0, 0, 0, 460, 461, 5, 1, 0, 0, 461, 462, 3, 18, 9, 0, 462, 464, 3, 92, 46, 0, 463, 465, 3, 80, 40, 0, 464, 463, 1, 0, 0, 0, 464, 465, 1, 0, 0, 0, 465, 75, 1, 0, 0, 0, 466, 467, 5, 7, 0, 0, 467, 468, 3, 18, 9, 0, 468, 469, 3, 92, 46, 0, 469, 77, 1, 0, 0, 0, 470, 471, 5, 14, 0, 0, 471, 472, 3, 48, 24, 0, 472, 79, 1, 0, 0, 0, 473, 478, 3, 82, 41, 0, 474, 475, 5, 38, 0, 0, 475, 477, 3, 82, 41, 0, 476, 474, 1, 0, 0, 0, 477, 480, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 81, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 481, 482, 3, 54, 27, 0, 482, 483, 5, 36, 0, 0, 483, 484, 3, 58, 29, 0, 484, 83, 1, 0, 0, 0, 485, 486, 7, 5, 0, 0, 486, 85, 1, 0, 0, 0, 487, 490, 3, 88, 44, 0, 488, 490, 3, 90, 45, 0, 489, 487, 1, 0, 0, 0, 489, 488, 1, 0, 0, 0, 490, 87, 1, 0, 0, 0, 491, 493, 7, 0, 0, 0, 492, 491, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 495, 5, 32, 0, 0, 495, 89, 1, 0, 0, 0, 496, 498, 7, 0, 0, 0, 497, 496, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 5, 31, 0, 0, 500, 91, 1, 0, 0, 0, 501, 502, 5, 30, 0, 0, 502, 93, 1, 0, 0, 0, 503, 504, 7, 6, 0, 0, 504, 95, 1, 0, 0, 0, 505, 506, 5, 5, 0, 0, 506, 507, 3, 98, 49, 0, 507, 97, 1, 0, 0, 0, 508, 509, 5, 68, 0, 0, 509, 510, 3, 2, 1, 0, 510, 511, 5, 69, 0, 0, 511, 99, 1, 0, 0, 0, 512, 513, 5, 17, 0, 0, 513, 514, 5, 105, 0, 0, 514, 101, 1, 0, 0, 0, 515, 516, 5, 12, 0, 0, 516, 517, 5, 109, 0, 0, 517, 103, 1, 0, 0, 0, 518, 519, 5, 3, 0, 0, 519, 522, 5, 89, 0, 0, 520, 521, 5, 87, 0, 0, 521, 523, 3, 50, 25, 0, 522, 520, 1, 0, 0, 0, 522, 523, 1, 0, 0, 0, 523, 533, 1, 0, 0, 0, 524, 525, 5, 88, 0, 0, 525, 530, 3, 106, 53, 0, 526, 527, 5, 38, 0, 0, 527, 529, 3, 106, 53, 0, 528, 526, 1, 0, 0, 0, 529, 532, 1, 0, 0, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 534, 1, 0, 0, 0, 532, 530, 1, 0, 0, 0, 533, 524, 1, 0, 0, 0, 533, 534, 1, 0, 0, 0, 534, 105, 1, 0, 0, 0, 535, 536, 3, 50, 25, 0, 536, 537, 5, 36, 0, 0, 537, 539, 1, 0, 0, 0, 538, 535, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 540, 1, 0, 0, 0, 540, 541, 3, 50, 25, 0, 541, 107, 1, 0, 0, 0, 542, 543, 5, 11, 0, 0, 543, 544, 5, 25, 0, 0, 544, 545, 5, 87, 0, 0, 545, 546, 3, 52, 26, 0, 546, 109, 1, 0, 0, 0, 52, 121, 130, 146, 158, 167, 175, 179, 187, 189, 194, 201, 206, 213, 219, 227, 229, 240, 247, 258, 261, 275, 283, 291, 295, 301, 309, 322, 326, 330, 337, 341, 347, 354, 362, 370, 392, 403, 414, 419, 430, 435, 439, 453, 464, 478, 489, 492, 497, 522, 530, 533, 538] \ No newline at end of file +[4, 1, 124, 554, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 122, 8, 1, 10, 1, 12, 1, 125, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 133, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 149, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 161, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 168, 8, 5, 10, 5, 12, 5, 171, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 178, 8, 5, 1, 5, 1, 5, 3, 5, 182, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 190, 8, 5, 10, 5, 12, 5, 193, 9, 5, 1, 6, 1, 6, 3, 6, 197, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 204, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 209, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 216, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 222, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 230, 8, 8, 10, 8, 12, 8, 233, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 243, 8, 9, 1, 9, 1, 9, 1, 9, 5, 9, 248, 8, 9, 10, 9, 12, 9, 251, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 259, 8, 10, 10, 10, 12, 10, 262, 9, 10, 3, 10, 264, 8, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 276, 8, 13, 10, 13, 12, 13, 279, 9, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 286, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 292, 8, 15, 10, 15, 12, 15, 295, 9, 15, 1, 15, 3, 15, 298, 8, 15, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 304, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 310, 8, 18, 10, 18, 12, 18, 313, 9, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 323, 8, 20, 10, 20, 12, 20, 326, 9, 20, 1, 20, 3, 20, 329, 8, 20, 1, 20, 1, 20, 3, 20, 333, 8, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 3, 22, 340, 8, 22, 1, 22, 1, 22, 3, 22, 344, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 350, 8, 23, 1, 24, 1, 24, 1, 24, 5, 24, 355, 8, 24, 10, 24, 12, 24, 358, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 363, 8, 25, 10, 25, 12, 25, 366, 9, 25, 1, 26, 1, 26, 1, 26, 5, 26, 371, 8, 26, 10, 26, 12, 26, 374, 9, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 393, 8, 29, 10, 29, 12, 29, 396, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 404, 8, 29, 10, 29, 12, 29, 407, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 415, 8, 29, 10, 29, 12, 29, 418, 9, 29, 1, 29, 1, 29, 3, 29, 422, 8, 29, 1, 30, 1, 30, 3, 30, 426, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 435, 8, 32, 10, 32, 12, 32, 438, 9, 32, 1, 33, 1, 33, 3, 33, 442, 8, 33, 1, 33, 1, 33, 3, 33, 446, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 458, 8, 36, 10, 36, 12, 36, 461, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 471, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 483, 8, 41, 10, 41, 12, 41, 486, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 44, 1, 44, 3, 44, 496, 8, 44, 1, 45, 3, 45, 499, 8, 45, 1, 45, 1, 45, 1, 46, 3, 46, 504, 8, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 3, 53, 529, 8, 53, 1, 53, 1, 53, 1, 53, 1, 53, 5, 53, 535, 8, 53, 10, 53, 12, 53, 538, 9, 53, 3, 53, 540, 8, 53, 1, 54, 1, 54, 1, 54, 3, 54, 545, 8, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 0, 4, 2, 10, 16, 18, 56, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 0, 7, 1, 0, 63, 64, 1, 0, 65, 67, 1, 0, 71, 72, 2, 0, 35, 35, 39, 39, 1, 0, 42, 43, 2, 0, 41, 41, 55, 55, 2, 0, 56, 56, 58, 62, 580, 0, 112, 1, 0, 0, 0, 2, 115, 1, 0, 0, 0, 4, 132, 1, 0, 0, 0, 6, 148, 1, 0, 0, 0, 8, 150, 1, 0, 0, 0, 10, 181, 1, 0, 0, 0, 12, 208, 1, 0, 0, 0, 14, 215, 1, 0, 0, 0, 16, 221, 1, 0, 0, 0, 18, 242, 1, 0, 0, 0, 20, 252, 1, 0, 0, 0, 22, 267, 1, 0, 0, 0, 24, 269, 1, 0, 0, 0, 26, 272, 1, 0, 0, 0, 28, 285, 1, 0, 0, 0, 30, 287, 1, 0, 0, 0, 32, 299, 1, 0, 0, 0, 34, 303, 1, 0, 0, 0, 36, 305, 1, 0, 0, 0, 38, 314, 1, 0, 0, 0, 40, 318, 1, 0, 0, 0, 42, 334, 1, 0, 0, 0, 44, 337, 1, 0, 0, 0, 46, 345, 1, 0, 0, 0, 48, 351, 1, 0, 0, 0, 50, 359, 1, 0, 0, 0, 52, 367, 1, 0, 0, 0, 54, 375, 1, 0, 0, 0, 56, 377, 1, 0, 0, 0, 58, 421, 1, 0, 0, 0, 60, 425, 1, 0, 0, 0, 62, 427, 1, 0, 0, 0, 64, 430, 1, 0, 0, 0, 66, 439, 1, 0, 0, 0, 68, 447, 1, 0, 0, 0, 70, 450, 1, 0, 0, 0, 72, 453, 1, 0, 0, 0, 74, 462, 1, 0, 0, 0, 76, 466, 1, 0, 0, 0, 78, 472, 1, 0, 0, 0, 80, 476, 1, 0, 0, 0, 82, 479, 1, 0, 0, 0, 84, 487, 1, 0, 0, 0, 86, 491, 1, 0, 0, 0, 88, 495, 1, 0, 0, 0, 90, 498, 1, 0, 0, 0, 92, 503, 1, 0, 0, 0, 94, 507, 1, 0, 0, 0, 96, 509, 1, 0, 0, 0, 98, 511, 1, 0, 0, 0, 100, 514, 1, 0, 0, 0, 102, 518, 1, 0, 0, 0, 104, 521, 1, 0, 0, 0, 106, 524, 1, 0, 0, 0, 108, 544, 1, 0, 0, 0, 110, 548, 1, 0, 0, 0, 112, 113, 3, 2, 1, 0, 113, 114, 5, 0, 0, 1, 114, 1, 1, 0, 0, 0, 115, 116, 6, 1, -1, 0, 116, 117, 3, 4, 2, 0, 117, 123, 1, 0, 0, 0, 118, 119, 10, 1, 0, 0, 119, 120, 5, 29, 0, 0, 120, 122, 3, 6, 3, 0, 121, 118, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 3, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 126, 133, 3, 98, 49, 0, 127, 133, 3, 30, 15, 0, 128, 133, 3, 24, 12, 0, 129, 133, 3, 40, 20, 0, 130, 133, 3, 102, 51, 0, 131, 133, 3, 104, 52, 0, 132, 126, 1, 0, 0, 0, 132, 127, 1, 0, 0, 0, 132, 128, 1, 0, 0, 0, 132, 129, 1, 0, 0, 0, 132, 130, 1, 0, 0, 0, 132, 131, 1, 0, 0, 0, 133, 5, 1, 0, 0, 0, 134, 149, 3, 42, 21, 0, 135, 149, 3, 46, 23, 0, 136, 149, 3, 62, 31, 0, 137, 149, 3, 110, 55, 0, 138, 149, 3, 68, 34, 0, 139, 149, 3, 64, 32, 0, 140, 149, 3, 44, 22, 0, 141, 149, 3, 8, 4, 0, 142, 149, 3, 70, 35, 0, 143, 149, 3, 72, 36, 0, 144, 149, 3, 76, 38, 0, 145, 149, 3, 78, 39, 0, 146, 149, 3, 106, 53, 0, 147, 149, 3, 80, 40, 0, 148, 134, 1, 0, 0, 0, 148, 135, 1, 0, 0, 0, 148, 136, 1, 0, 0, 0, 148, 137, 1, 0, 0, 0, 148, 138, 1, 0, 0, 0, 148, 139, 1, 0, 0, 0, 148, 140, 1, 0, 0, 0, 148, 141, 1, 0, 0, 0, 148, 142, 1, 0, 0, 0, 148, 143, 1, 0, 0, 0, 148, 144, 1, 0, 0, 0, 148, 145, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 147, 1, 0, 0, 0, 149, 7, 1, 0, 0, 0, 150, 151, 5, 20, 0, 0, 151, 152, 3, 10, 5, 0, 152, 9, 1, 0, 0, 0, 153, 154, 6, 5, -1, 0, 154, 155, 5, 48, 0, 0, 155, 182, 3, 10, 5, 7, 156, 182, 3, 14, 7, 0, 157, 182, 3, 12, 6, 0, 158, 160, 3, 14, 7, 0, 159, 161, 5, 48, 0, 0, 160, 159, 1, 0, 0, 0, 160, 161, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 5, 45, 0, 0, 163, 164, 5, 44, 0, 0, 164, 169, 3, 14, 7, 0, 165, 166, 5, 38, 0, 0, 166, 168, 3, 14, 7, 0, 167, 165, 1, 0, 0, 0, 168, 171, 1, 0, 0, 0, 169, 167, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 172, 1, 0, 0, 0, 171, 169, 1, 0, 0, 0, 172, 173, 5, 54, 0, 0, 173, 182, 1, 0, 0, 0, 174, 175, 3, 14, 7, 0, 175, 177, 5, 46, 0, 0, 176, 178, 5, 48, 0, 0, 177, 176, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 179, 1, 0, 0, 0, 179, 180, 5, 49, 0, 0, 180, 182, 1, 0, 0, 0, 181, 153, 1, 0, 0, 0, 181, 156, 1, 0, 0, 0, 181, 157, 1, 0, 0, 0, 181, 158, 1, 0, 0, 0, 181, 174, 1, 0, 0, 0, 182, 191, 1, 0, 0, 0, 183, 184, 10, 4, 0, 0, 184, 185, 5, 34, 0, 0, 185, 190, 3, 10, 5, 5, 186, 187, 10, 3, 0, 0, 187, 188, 5, 51, 0, 0, 188, 190, 3, 10, 5, 4, 189, 183, 1, 0, 0, 0, 189, 186, 1, 0, 0, 0, 190, 193, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 11, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 194, 196, 3, 14, 7, 0, 195, 197, 5, 48, 0, 0, 196, 195, 1, 0, 0, 0, 196, 197, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 199, 5, 47, 0, 0, 199, 200, 3, 94, 47, 0, 200, 209, 1, 0, 0, 0, 201, 203, 3, 14, 7, 0, 202, 204, 5, 48, 0, 0, 203, 202, 1, 0, 0, 0, 203, 204, 1, 0, 0, 0, 204, 205, 1, 0, 0, 0, 205, 206, 5, 53, 0, 0, 206, 207, 3, 94, 47, 0, 207, 209, 1, 0, 0, 0, 208, 194, 1, 0, 0, 0, 208, 201, 1, 0, 0, 0, 209, 13, 1, 0, 0, 0, 210, 216, 3, 16, 8, 0, 211, 212, 3, 16, 8, 0, 212, 213, 3, 96, 48, 0, 213, 214, 3, 16, 8, 0, 214, 216, 1, 0, 0, 0, 215, 210, 1, 0, 0, 0, 215, 211, 1, 0, 0, 0, 216, 15, 1, 0, 0, 0, 217, 218, 6, 8, -1, 0, 218, 222, 3, 18, 9, 0, 219, 220, 7, 0, 0, 0, 220, 222, 3, 16, 8, 3, 221, 217, 1, 0, 0, 0, 221, 219, 1, 0, 0, 0, 222, 231, 1, 0, 0, 0, 223, 224, 10, 2, 0, 0, 224, 225, 7, 1, 0, 0, 225, 230, 3, 16, 8, 3, 226, 227, 10, 1, 0, 0, 227, 228, 7, 0, 0, 0, 228, 230, 3, 16, 8, 2, 229, 223, 1, 0, 0, 0, 229, 226, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 17, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 235, 6, 9, -1, 0, 235, 243, 3, 58, 29, 0, 236, 243, 3, 48, 24, 0, 237, 243, 3, 20, 10, 0, 238, 239, 5, 44, 0, 0, 239, 240, 3, 10, 5, 0, 240, 241, 5, 54, 0, 0, 241, 243, 1, 0, 0, 0, 242, 234, 1, 0, 0, 0, 242, 236, 1, 0, 0, 0, 242, 237, 1, 0, 0, 0, 242, 238, 1, 0, 0, 0, 243, 249, 1, 0, 0, 0, 244, 245, 10, 1, 0, 0, 245, 246, 5, 37, 0, 0, 246, 248, 3, 22, 11, 0, 247, 244, 1, 0, 0, 0, 248, 251, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 19, 1, 0, 0, 0, 251, 249, 1, 0, 0, 0, 252, 253, 3, 54, 27, 0, 253, 263, 5, 44, 0, 0, 254, 264, 5, 65, 0, 0, 255, 260, 3, 10, 5, 0, 256, 257, 5, 38, 0, 0, 257, 259, 3, 10, 5, 0, 258, 256, 1, 0, 0, 0, 259, 262, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 264, 1, 0, 0, 0, 262, 260, 1, 0, 0, 0, 263, 254, 1, 0, 0, 0, 263, 255, 1, 0, 0, 0, 263, 264, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 266, 5, 54, 0, 0, 266, 21, 1, 0, 0, 0, 267, 268, 3, 54, 27, 0, 268, 23, 1, 0, 0, 0, 269, 270, 5, 16, 0, 0, 270, 271, 3, 26, 13, 0, 271, 25, 1, 0, 0, 0, 272, 277, 3, 28, 14, 0, 273, 274, 5, 38, 0, 0, 274, 276, 3, 28, 14, 0, 275, 273, 1, 0, 0, 0, 276, 279, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 277, 278, 1, 0, 0, 0, 278, 27, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 280, 286, 3, 10, 5, 0, 281, 282, 3, 48, 24, 0, 282, 283, 5, 36, 0, 0, 283, 284, 3, 10, 5, 0, 284, 286, 1, 0, 0, 0, 285, 280, 1, 0, 0, 0, 285, 281, 1, 0, 0, 0, 286, 29, 1, 0, 0, 0, 287, 288, 5, 6, 0, 0, 288, 293, 3, 32, 16, 0, 289, 290, 5, 38, 0, 0, 290, 292, 3, 32, 16, 0, 291, 289, 1, 0, 0, 0, 292, 295, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 297, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 296, 298, 3, 34, 17, 0, 297, 296, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 31, 1, 0, 0, 0, 299, 300, 5, 25, 0, 0, 300, 33, 1, 0, 0, 0, 301, 304, 3, 36, 18, 0, 302, 304, 3, 38, 19, 0, 303, 301, 1, 0, 0, 0, 303, 302, 1, 0, 0, 0, 304, 35, 1, 0, 0, 0, 305, 306, 5, 76, 0, 0, 306, 311, 3, 32, 16, 0, 307, 308, 5, 38, 0, 0, 308, 310, 3, 32, 16, 0, 309, 307, 1, 0, 0, 0, 310, 313, 1, 0, 0, 0, 311, 309, 1, 0, 0, 0, 311, 312, 1, 0, 0, 0, 312, 37, 1, 0, 0, 0, 313, 311, 1, 0, 0, 0, 314, 315, 5, 69, 0, 0, 315, 316, 3, 36, 18, 0, 316, 317, 5, 70, 0, 0, 317, 39, 1, 0, 0, 0, 318, 319, 5, 13, 0, 0, 319, 324, 3, 32, 16, 0, 320, 321, 5, 38, 0, 0, 321, 323, 3, 32, 16, 0, 322, 320, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 328, 1, 0, 0, 0, 326, 324, 1, 0, 0, 0, 327, 329, 3, 26, 13, 0, 328, 327, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 332, 1, 0, 0, 0, 330, 331, 5, 33, 0, 0, 331, 333, 3, 26, 13, 0, 332, 330, 1, 0, 0, 0, 332, 333, 1, 0, 0, 0, 333, 41, 1, 0, 0, 0, 334, 335, 5, 4, 0, 0, 335, 336, 3, 26, 13, 0, 336, 43, 1, 0, 0, 0, 337, 339, 5, 19, 0, 0, 338, 340, 3, 26, 13, 0, 339, 338, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 343, 1, 0, 0, 0, 341, 342, 5, 33, 0, 0, 342, 344, 3, 26, 13, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 45, 1, 0, 0, 0, 345, 346, 5, 8, 0, 0, 346, 349, 3, 26, 13, 0, 347, 348, 5, 33, 0, 0, 348, 350, 3, 26, 13, 0, 349, 347, 1, 0, 0, 0, 349, 350, 1, 0, 0, 0, 350, 47, 1, 0, 0, 0, 351, 356, 3, 54, 27, 0, 352, 353, 5, 40, 0, 0, 353, 355, 3, 54, 27, 0, 354, 352, 1, 0, 0, 0, 355, 358, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 49, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 359, 364, 3, 56, 28, 0, 360, 361, 5, 40, 0, 0, 361, 363, 3, 56, 28, 0, 362, 360, 1, 0, 0, 0, 363, 366, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 364, 365, 1, 0, 0, 0, 365, 51, 1, 0, 0, 0, 366, 364, 1, 0, 0, 0, 367, 372, 3, 50, 25, 0, 368, 369, 5, 38, 0, 0, 369, 371, 3, 50, 25, 0, 370, 368, 1, 0, 0, 0, 371, 374, 1, 0, 0, 0, 372, 370, 1, 0, 0, 0, 372, 373, 1, 0, 0, 0, 373, 53, 1, 0, 0, 0, 374, 372, 1, 0, 0, 0, 375, 376, 7, 2, 0, 0, 376, 55, 1, 0, 0, 0, 377, 378, 5, 80, 0, 0, 378, 57, 1, 0, 0, 0, 379, 422, 5, 49, 0, 0, 380, 381, 3, 92, 46, 0, 381, 382, 5, 71, 0, 0, 382, 422, 1, 0, 0, 0, 383, 422, 3, 90, 45, 0, 384, 422, 3, 92, 46, 0, 385, 422, 3, 86, 43, 0, 386, 422, 3, 60, 30, 0, 387, 422, 3, 94, 47, 0, 388, 389, 5, 69, 0, 0, 389, 394, 3, 88, 44, 0, 390, 391, 5, 38, 0, 0, 391, 393, 3, 88, 44, 0, 392, 390, 1, 0, 0, 0, 393, 396, 1, 0, 0, 0, 394, 392, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 397, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0, 397, 398, 5, 70, 0, 0, 398, 422, 1, 0, 0, 0, 399, 400, 5, 69, 0, 0, 400, 405, 3, 86, 43, 0, 401, 402, 5, 38, 0, 0, 402, 404, 3, 86, 43, 0, 403, 401, 1, 0, 0, 0, 404, 407, 1, 0, 0, 0, 405, 403, 1, 0, 0, 0, 405, 406, 1, 0, 0, 0, 406, 408, 1, 0, 0, 0, 407, 405, 1, 0, 0, 0, 408, 409, 5, 70, 0, 0, 409, 422, 1, 0, 0, 0, 410, 411, 5, 69, 0, 0, 411, 416, 3, 94, 47, 0, 412, 413, 5, 38, 0, 0, 413, 415, 3, 94, 47, 0, 414, 412, 1, 0, 0, 0, 415, 418, 1, 0, 0, 0, 416, 414, 1, 0, 0, 0, 416, 417, 1, 0, 0, 0, 417, 419, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 419, 420, 5, 70, 0, 0, 420, 422, 1, 0, 0, 0, 421, 379, 1, 0, 0, 0, 421, 380, 1, 0, 0, 0, 421, 383, 1, 0, 0, 0, 421, 384, 1, 0, 0, 0, 421, 385, 1, 0, 0, 0, 421, 386, 1, 0, 0, 0, 421, 387, 1, 0, 0, 0, 421, 388, 1, 0, 0, 0, 421, 399, 1, 0, 0, 0, 421, 410, 1, 0, 0, 0, 422, 59, 1, 0, 0, 0, 423, 426, 5, 52, 0, 0, 424, 426, 5, 68, 0, 0, 425, 423, 1, 0, 0, 0, 425, 424, 1, 0, 0, 0, 426, 61, 1, 0, 0, 0, 427, 428, 5, 10, 0, 0, 428, 429, 5, 31, 0, 0, 429, 63, 1, 0, 0, 0, 430, 431, 5, 18, 0, 0, 431, 436, 3, 66, 33, 0, 432, 433, 5, 38, 0, 0, 433, 435, 3, 66, 33, 0, 434, 432, 1, 0, 0, 0, 435, 438, 1, 0, 0, 0, 436, 434, 1, 0, 0, 0, 436, 437, 1, 0, 0, 0, 437, 65, 1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 439, 441, 3, 10, 5, 0, 440, 442, 7, 3, 0, 0, 441, 440, 1, 0, 0, 0, 441, 442, 1, 0, 0, 0, 442, 445, 1, 0, 0, 0, 443, 444, 5, 50, 0, 0, 444, 446, 7, 4, 0, 0, 445, 443, 1, 0, 0, 0, 445, 446, 1, 0, 0, 0, 446, 67, 1, 0, 0, 0, 447, 448, 5, 9, 0, 0, 448, 449, 3, 52, 26, 0, 449, 69, 1, 0, 0, 0, 450, 451, 5, 2, 0, 0, 451, 452, 3, 52, 26, 0, 452, 71, 1, 0, 0, 0, 453, 454, 5, 15, 0, 0, 454, 459, 3, 74, 37, 0, 455, 456, 5, 38, 0, 0, 456, 458, 3, 74, 37, 0, 457, 455, 1, 0, 0, 0, 458, 461, 1, 0, 0, 0, 459, 457, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 73, 1, 0, 0, 0, 461, 459, 1, 0, 0, 0, 462, 463, 3, 50, 25, 0, 463, 464, 5, 84, 0, 0, 464, 465, 3, 50, 25, 0, 465, 75, 1, 0, 0, 0, 466, 467, 5, 1, 0, 0, 467, 468, 3, 18, 9, 0, 468, 470, 3, 94, 47, 0, 469, 471, 3, 82, 41, 0, 470, 469, 1, 0, 0, 0, 470, 471, 1, 0, 0, 0, 471, 77, 1, 0, 0, 0, 472, 473, 5, 7, 0, 0, 473, 474, 3, 18, 9, 0, 474, 475, 3, 94, 47, 0, 475, 79, 1, 0, 0, 0, 476, 477, 5, 14, 0, 0, 477, 478, 3, 48, 24, 0, 478, 81, 1, 0, 0, 0, 479, 484, 3, 84, 42, 0, 480, 481, 5, 38, 0, 0, 481, 483, 3, 84, 42, 0, 482, 480, 1, 0, 0, 0, 483, 486, 1, 0, 0, 0, 484, 482, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 83, 1, 0, 0, 0, 486, 484, 1, 0, 0, 0, 487, 488, 3, 54, 27, 0, 488, 489, 5, 36, 0, 0, 489, 490, 3, 58, 29, 0, 490, 85, 1, 0, 0, 0, 491, 492, 7, 5, 0, 0, 492, 87, 1, 0, 0, 0, 493, 496, 3, 90, 45, 0, 494, 496, 3, 92, 46, 0, 495, 493, 1, 0, 0, 0, 495, 494, 1, 0, 0, 0, 496, 89, 1, 0, 0, 0, 497, 499, 7, 0, 0, 0, 498, 497, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 1, 0, 0, 0, 500, 501, 5, 32, 0, 0, 501, 91, 1, 0, 0, 0, 502, 504, 7, 0, 0, 0, 503, 502, 1, 0, 0, 0, 503, 504, 1, 0, 0, 0, 504, 505, 1, 0, 0, 0, 505, 506, 5, 31, 0, 0, 506, 93, 1, 0, 0, 0, 507, 508, 5, 30, 0, 0, 508, 95, 1, 0, 0, 0, 509, 510, 7, 6, 0, 0, 510, 97, 1, 0, 0, 0, 511, 512, 5, 5, 0, 0, 512, 513, 3, 100, 50, 0, 513, 99, 1, 0, 0, 0, 514, 515, 5, 69, 0, 0, 515, 516, 3, 2, 1, 0, 516, 517, 5, 70, 0, 0, 517, 101, 1, 0, 0, 0, 518, 519, 5, 17, 0, 0, 519, 520, 5, 106, 0, 0, 520, 103, 1, 0, 0, 0, 521, 522, 5, 12, 0, 0, 522, 523, 5, 110, 0, 0, 523, 105, 1, 0, 0, 0, 524, 525, 5, 3, 0, 0, 525, 528, 5, 90, 0, 0, 526, 527, 5, 88, 0, 0, 527, 529, 3, 50, 25, 0, 528, 526, 1, 0, 0, 0, 528, 529, 1, 0, 0, 0, 529, 539, 1, 0, 0, 0, 530, 531, 5, 89, 0, 0, 531, 536, 3, 108, 54, 0, 532, 533, 5, 38, 0, 0, 533, 535, 3, 108, 54, 0, 534, 532, 1, 0, 0, 0, 535, 538, 1, 0, 0, 0, 536, 534, 1, 0, 0, 0, 536, 537, 1, 0, 0, 0, 537, 540, 1, 0, 0, 0, 538, 536, 1, 0, 0, 0, 539, 530, 1, 0, 0, 0, 539, 540, 1, 0, 0, 0, 540, 107, 1, 0, 0, 0, 541, 542, 3, 50, 25, 0, 542, 543, 5, 36, 0, 0, 543, 545, 1, 0, 0, 0, 544, 541, 1, 0, 0, 0, 544, 545, 1, 0, 0, 0, 545, 546, 1, 0, 0, 0, 546, 547, 3, 50, 25, 0, 547, 109, 1, 0, 0, 0, 548, 549, 5, 11, 0, 0, 549, 550, 5, 25, 0, 0, 550, 551, 5, 88, 0, 0, 551, 552, 3, 52, 26, 0, 552, 111, 1, 0, 0, 0, 53, 123, 132, 148, 160, 169, 177, 181, 189, 191, 196, 203, 208, 215, 221, 229, 231, 242, 249, 260, 263, 277, 285, 293, 297, 303, 311, 324, 328, 332, 339, 343, 349, 356, 364, 372, 394, 405, 416, 421, 425, 436, 441, 445, 459, 470, 484, 495, 498, 503, 528, 536, 539, 544] \ No newline at end of file diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.tokens b/packages/kbn-esql-ast/src/antlr/esql_parser.tokens index 30ce0d5eea55b..04798fc3dca8a 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.tokens +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.tokens @@ -65,62 +65,63 @@ MINUS=64 ASTERISK=65 SLASH=66 PERCENT=67 -OPENING_BRACKET=68 -CLOSING_BRACKET=69 -UNQUOTED_IDENTIFIER=70 -QUOTED_IDENTIFIER=71 -EXPR_LINE_COMMENT=72 -EXPR_MULTILINE_COMMENT=73 -EXPR_WS=74 -METADATA=75 -FROM_LINE_COMMENT=76 -FROM_MULTILINE_COMMENT=77 -FROM_WS=78 -ID_PATTERN=79 -PROJECT_LINE_COMMENT=80 -PROJECT_MULTILINE_COMMENT=81 -PROJECT_WS=82 -AS=83 -RENAME_LINE_COMMENT=84 -RENAME_MULTILINE_COMMENT=85 -RENAME_WS=86 -ON=87 -WITH=88 -ENRICH_POLICY_NAME=89 -ENRICH_LINE_COMMENT=90 -ENRICH_MULTILINE_COMMENT=91 -ENRICH_WS=92 -ENRICH_FIELD_LINE_COMMENT=93 -ENRICH_FIELD_MULTILINE_COMMENT=94 -ENRICH_FIELD_WS=95 -LOOKUP_LINE_COMMENT=96 -LOOKUP_MULTILINE_COMMENT=97 -LOOKUP_WS=98 -LOOKUP_FIELD_LINE_COMMENT=99 -LOOKUP_FIELD_MULTILINE_COMMENT=100 -LOOKUP_FIELD_WS=101 -MVEXPAND_LINE_COMMENT=102 -MVEXPAND_MULTILINE_COMMENT=103 -MVEXPAND_WS=104 -INFO=105 -SHOW_LINE_COMMENT=106 -SHOW_MULTILINE_COMMENT=107 -SHOW_WS=108 -FUNCTIONS=109 -META_LINE_COMMENT=110 -META_MULTILINE_COMMENT=111 -META_WS=112 -COLON=113 -SETTING=114 -SETTING_LINE_COMMENT=115 -SETTTING_MULTILINE_COMMENT=116 -SETTING_WS=117 -METRICS_LINE_COMMENT=118 -METRICS_MULTILINE_COMMENT=119 -METRICS_WS=120 -CLOSING_METRICS_LINE_COMMENT=121 -CLOSING_METRICS_MULTILINE_COMMENT=122 -CLOSING_METRICS_WS=123 +NAMED_OR_POSITIONAL_PARAM=68 +OPENING_BRACKET=69 +CLOSING_BRACKET=70 +UNQUOTED_IDENTIFIER=71 +QUOTED_IDENTIFIER=72 +EXPR_LINE_COMMENT=73 +EXPR_MULTILINE_COMMENT=74 +EXPR_WS=75 +METADATA=76 +FROM_LINE_COMMENT=77 +FROM_MULTILINE_COMMENT=78 +FROM_WS=79 +ID_PATTERN=80 +PROJECT_LINE_COMMENT=81 +PROJECT_MULTILINE_COMMENT=82 +PROJECT_WS=83 +AS=84 +RENAME_LINE_COMMENT=85 +RENAME_MULTILINE_COMMENT=86 +RENAME_WS=87 +ON=88 +WITH=89 +ENRICH_POLICY_NAME=90 +ENRICH_LINE_COMMENT=91 +ENRICH_MULTILINE_COMMENT=92 +ENRICH_WS=93 +ENRICH_FIELD_LINE_COMMENT=94 +ENRICH_FIELD_MULTILINE_COMMENT=95 +ENRICH_FIELD_WS=96 +LOOKUP_LINE_COMMENT=97 +LOOKUP_MULTILINE_COMMENT=98 +LOOKUP_WS=99 +LOOKUP_FIELD_LINE_COMMENT=100 +LOOKUP_FIELD_MULTILINE_COMMENT=101 +LOOKUP_FIELD_WS=102 +MVEXPAND_LINE_COMMENT=103 +MVEXPAND_MULTILINE_COMMENT=104 +MVEXPAND_WS=105 +INFO=106 +SHOW_LINE_COMMENT=107 +SHOW_MULTILINE_COMMENT=108 +SHOW_WS=109 +FUNCTIONS=110 +META_LINE_COMMENT=111 +META_MULTILINE_COMMENT=112 +META_WS=113 +COLON=114 +SETTING=115 +SETTING_LINE_COMMENT=116 +SETTTING_MULTILINE_COMMENT=117 +SETTING_WS=118 +METRICS_LINE_COMMENT=119 +METRICS_MULTILINE_COMMENT=120 +METRICS_WS=121 +CLOSING_METRICS_LINE_COMMENT=122 +CLOSING_METRICS_MULTILINE_COMMENT=123 +CLOSING_METRICS_WS=124 'dissect'=1 'drop'=2 'enrich'=3 @@ -177,11 +178,11 @@ CLOSING_METRICS_WS=123 '*'=65 '/'=66 '%'=67 -']'=69 -'metadata'=75 -'as'=83 -'on'=87 -'with'=88 -'info'=105 -'functions'=109 -':'=113 +']'=70 +'metadata'=76 +'as'=84 +'on'=88 +'with'=89 +'info'=106 +'functions'=110 +':'=114 diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.ts b/packages/kbn-esql-ast/src/antlr/esql_parser.ts index 7b132ef4a3358..5181349c62c88 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.ts +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.ts @@ -85,62 +85,63 @@ export default class esql_parser extends Parser { public static readonly ASTERISK = 65; public static readonly SLASH = 66; public static readonly PERCENT = 67; - public static readonly OPENING_BRACKET = 68; - public static readonly CLOSING_BRACKET = 69; - public static readonly UNQUOTED_IDENTIFIER = 70; - public static readonly QUOTED_IDENTIFIER = 71; - public static readonly EXPR_LINE_COMMENT = 72; - public static readonly EXPR_MULTILINE_COMMENT = 73; - public static readonly EXPR_WS = 74; - public static readonly METADATA = 75; - public static readonly FROM_LINE_COMMENT = 76; - public static readonly FROM_MULTILINE_COMMENT = 77; - public static readonly FROM_WS = 78; - public static readonly ID_PATTERN = 79; - public static readonly PROJECT_LINE_COMMENT = 80; - public static readonly PROJECT_MULTILINE_COMMENT = 81; - public static readonly PROJECT_WS = 82; - public static readonly AS = 83; - public static readonly RENAME_LINE_COMMENT = 84; - public static readonly RENAME_MULTILINE_COMMENT = 85; - public static readonly RENAME_WS = 86; - public static readonly ON = 87; - public static readonly WITH = 88; - public static readonly ENRICH_POLICY_NAME = 89; - public static readonly ENRICH_LINE_COMMENT = 90; - public static readonly ENRICH_MULTILINE_COMMENT = 91; - public static readonly ENRICH_WS = 92; - public static readonly ENRICH_FIELD_LINE_COMMENT = 93; - public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 94; - public static readonly ENRICH_FIELD_WS = 95; - public static readonly LOOKUP_LINE_COMMENT = 96; - public static readonly LOOKUP_MULTILINE_COMMENT = 97; - public static readonly LOOKUP_WS = 98; - public static readonly LOOKUP_FIELD_LINE_COMMENT = 99; - public static readonly LOOKUP_FIELD_MULTILINE_COMMENT = 100; - public static readonly LOOKUP_FIELD_WS = 101; - public static readonly MVEXPAND_LINE_COMMENT = 102; - public static readonly MVEXPAND_MULTILINE_COMMENT = 103; - public static readonly MVEXPAND_WS = 104; - public static readonly INFO = 105; - public static readonly SHOW_LINE_COMMENT = 106; - public static readonly SHOW_MULTILINE_COMMENT = 107; - public static readonly SHOW_WS = 108; - public static readonly FUNCTIONS = 109; - public static readonly META_LINE_COMMENT = 110; - public static readonly META_MULTILINE_COMMENT = 111; - public static readonly META_WS = 112; - public static readonly COLON = 113; - public static readonly SETTING = 114; - public static readonly SETTING_LINE_COMMENT = 115; - public static readonly SETTTING_MULTILINE_COMMENT = 116; - public static readonly SETTING_WS = 117; - public static readonly METRICS_LINE_COMMENT = 118; - public static readonly METRICS_MULTILINE_COMMENT = 119; - public static readonly METRICS_WS = 120; - public static readonly CLOSING_METRICS_LINE_COMMENT = 121; - public static readonly CLOSING_METRICS_MULTILINE_COMMENT = 122; - public static readonly CLOSING_METRICS_WS = 123; + public static readonly NAMED_OR_POSITIONAL_PARAM = 68; + public static readonly OPENING_BRACKET = 69; + public static readonly CLOSING_BRACKET = 70; + public static readonly UNQUOTED_IDENTIFIER = 71; + public static readonly QUOTED_IDENTIFIER = 72; + public static readonly EXPR_LINE_COMMENT = 73; + public static readonly EXPR_MULTILINE_COMMENT = 74; + public static readonly EXPR_WS = 75; + public static readonly METADATA = 76; + public static readonly FROM_LINE_COMMENT = 77; + public static readonly FROM_MULTILINE_COMMENT = 78; + public static readonly FROM_WS = 79; + public static readonly ID_PATTERN = 80; + public static readonly PROJECT_LINE_COMMENT = 81; + public static readonly PROJECT_MULTILINE_COMMENT = 82; + public static readonly PROJECT_WS = 83; + public static readonly AS = 84; + public static readonly RENAME_LINE_COMMENT = 85; + public static readonly RENAME_MULTILINE_COMMENT = 86; + public static readonly RENAME_WS = 87; + public static readonly ON = 88; + public static readonly WITH = 89; + public static readonly ENRICH_POLICY_NAME = 90; + public static readonly ENRICH_LINE_COMMENT = 91; + public static readonly ENRICH_MULTILINE_COMMENT = 92; + public static readonly ENRICH_WS = 93; + public static readonly ENRICH_FIELD_LINE_COMMENT = 94; + public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 95; + public static readonly ENRICH_FIELD_WS = 96; + public static readonly LOOKUP_LINE_COMMENT = 97; + public static readonly LOOKUP_MULTILINE_COMMENT = 98; + public static readonly LOOKUP_WS = 99; + public static readonly LOOKUP_FIELD_LINE_COMMENT = 100; + public static readonly LOOKUP_FIELD_MULTILINE_COMMENT = 101; + public static readonly LOOKUP_FIELD_WS = 102; + public static readonly MVEXPAND_LINE_COMMENT = 103; + public static readonly MVEXPAND_MULTILINE_COMMENT = 104; + public static readonly MVEXPAND_WS = 105; + public static readonly INFO = 106; + public static readonly SHOW_LINE_COMMENT = 107; + public static readonly SHOW_MULTILINE_COMMENT = 108; + public static readonly SHOW_WS = 109; + public static readonly FUNCTIONS = 110; + public static readonly META_LINE_COMMENT = 111; + public static readonly META_MULTILINE_COMMENT = 112; + public static readonly META_WS = 113; + public static readonly COLON = 114; + public static readonly SETTING = 115; + public static readonly SETTING_LINE_COMMENT = 116; + public static readonly SETTTING_MULTILINE_COMMENT = 117; + public static readonly SETTING_WS = 118; + public static readonly METRICS_LINE_COMMENT = 119; + public static readonly METRICS_MULTILINE_COMMENT = 120; + public static readonly METRICS_WS = 121; + public static readonly CLOSING_METRICS_LINE_COMMENT = 122; + public static readonly CLOSING_METRICS_MULTILINE_COMMENT = 123; + public static readonly CLOSING_METRICS_WS = 124; public static readonly EOF = Token.EOF; public static readonly RULE_singleStatement = 0; public static readonly RULE_query = 1; @@ -172,31 +173,32 @@ export default class esql_parser extends Parser { public static readonly RULE_identifier = 27; public static readonly RULE_identifierPattern = 28; public static readonly RULE_constant = 29; - public static readonly RULE_limitCommand = 30; - public static readonly RULE_sortCommand = 31; - public static readonly RULE_orderExpression = 32; - public static readonly RULE_keepCommand = 33; - public static readonly RULE_dropCommand = 34; - public static readonly RULE_renameCommand = 35; - public static readonly RULE_renameClause = 36; - public static readonly RULE_dissectCommand = 37; - public static readonly RULE_grokCommand = 38; - public static readonly RULE_mvExpandCommand = 39; - public static readonly RULE_commandOptions = 40; - public static readonly RULE_commandOption = 41; - public static readonly RULE_booleanValue = 42; - public static readonly RULE_numericValue = 43; - public static readonly RULE_decimalValue = 44; - public static readonly RULE_integerValue = 45; - public static readonly RULE_string = 46; - public static readonly RULE_comparisonOperator = 47; - public static readonly RULE_explainCommand = 48; - public static readonly RULE_subqueryExpression = 49; - public static readonly RULE_showCommand = 50; - public static readonly RULE_metaCommand = 51; - public static readonly RULE_enrichCommand = 52; - public static readonly RULE_enrichWithClause = 53; - public static readonly RULE_lookupCommand = 54; + public static readonly RULE_params = 30; + public static readonly RULE_limitCommand = 31; + public static readonly RULE_sortCommand = 32; + public static readonly RULE_orderExpression = 33; + public static readonly RULE_keepCommand = 34; + public static readonly RULE_dropCommand = 35; + public static readonly RULE_renameCommand = 36; + public static readonly RULE_renameClause = 37; + public static readonly RULE_dissectCommand = 38; + public static readonly RULE_grokCommand = 39; + public static readonly RULE_mvExpandCommand = 40; + public static readonly RULE_commandOptions = 41; + public static readonly RULE_commandOption = 42; + public static readonly RULE_booleanValue = 43; + public static readonly RULE_numericValue = 44; + public static readonly RULE_decimalValue = 45; + public static readonly RULE_integerValue = 46; + public static readonly RULE_string = 47; + public static readonly RULE_comparisonOperator = 48; + public static readonly RULE_explainCommand = 49; + public static readonly RULE_subqueryExpression = 50; + public static readonly RULE_showCommand = 51; + public static readonly RULE_metaCommand = 52; + public static readonly RULE_enrichCommand = 53; + public static readonly RULE_enrichWithClause = 54; + public static readonly RULE_lookupCommand = 55; public static readonly literalNames: (string | null)[] = [ null, "'dissect'", "'drop'", "'enrich'", "'eval'", "'explain'", @@ -233,10 +235,11 @@ export default class esql_parser extends Parser { "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", - null, "']'", null, null, + "']'", null, null, null, - null, "'metadata'", + null, null, + "'metadata'", null, null, null, null, null, null, @@ -296,6 +299,7 @@ export default class esql_parser extends Parser { "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", + "NAMED_OR_POSITIONAL_PARAM", "OPENING_BRACKET", "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", @@ -356,9 +360,9 @@ export default class esql_parser extends Parser { "field", "fromCommand", "indexIdentifier", "metadata", "metadataOption", "deprecated_metadata", "metricsCommand", "evalCommand", "statsCommand", "inlinestatsCommand", "qualifiedName", "qualifiedNamePattern", "qualifiedNamePatterns", - "identifier", "identifierPattern", "constant", "limitCommand", "sortCommand", - "orderExpression", "keepCommand", "dropCommand", "renameCommand", "renameClause", - "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", + "identifier", "identifierPattern", "constant", "params", "limitCommand", + "sortCommand", "orderExpression", "keepCommand", "dropCommand", "renameCommand", + "renameClause", "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", "commandOption", "booleanValue", "numericValue", "decimalValue", "integerValue", "string", "comparisonOperator", "explainCommand", "subqueryExpression", "showCommand", "metaCommand", "enrichCommand", "enrichWithClause", "lookupCommand", @@ -384,9 +388,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 110; + this.state = 112; this.query(0); - this.state = 111; + this.state = 113; this.match(esql_parser.EOF); } } @@ -428,11 +432,11 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 114; + this.state = 116; this.sourceCommand(); } this._ctx.stop = this._input.LT(-1); - this.state = 121; + this.state = 123; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 0, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -445,18 +449,18 @@ export default class esql_parser extends Parser { { localctx = new CompositeQueryContext(this, new QueryContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_query); - this.state = 116; + this.state = 118; if (!(this.precpred(this._ctx, 1))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); } - this.state = 117; + this.state = 119; this.match(esql_parser.PIPE); - this.state = 118; + this.state = 120; this.processingCommand(); } } } - this.state = 123; + this.state = 125; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 0, this._ctx); } @@ -481,48 +485,48 @@ export default class esql_parser extends Parser { let localctx: SourceCommandContext = new SourceCommandContext(this, this._ctx, this.state); this.enterRule(localctx, 4, esql_parser.RULE_sourceCommand); try { - this.state = 130; + this.state = 132; this._errHandler.sync(this); switch (this._input.LA(1)) { case 5: this.enterOuterAlt(localctx, 1); { - this.state = 124; + this.state = 126; this.explainCommand(); } break; case 6: this.enterOuterAlt(localctx, 2); { - this.state = 125; + this.state = 127; this.fromCommand(); } break; case 16: this.enterOuterAlt(localctx, 3); { - this.state = 126; + this.state = 128; this.rowCommand(); } break; case 13: this.enterOuterAlt(localctx, 4); { - this.state = 127; + this.state = 129; this.metricsCommand(); } break; case 17: this.enterOuterAlt(localctx, 5); { - this.state = 128; + this.state = 130; this.showCommand(); } break; case 12: this.enterOuterAlt(localctx, 6); { - this.state = 129; + this.state = 131; this.metaCommand(); } break; @@ -549,104 +553,104 @@ export default class esql_parser extends Parser { let localctx: ProcessingCommandContext = new ProcessingCommandContext(this, this._ctx, this.state); this.enterRule(localctx, 6, esql_parser.RULE_processingCommand); try { - this.state = 146; + this.state = 148; this._errHandler.sync(this); switch (this._input.LA(1)) { case 4: this.enterOuterAlt(localctx, 1); { - this.state = 132; + this.state = 134; this.evalCommand(); } break; case 8: this.enterOuterAlt(localctx, 2); { - this.state = 133; + this.state = 135; this.inlinestatsCommand(); } break; case 10: this.enterOuterAlt(localctx, 3); { - this.state = 134; + this.state = 136; this.limitCommand(); } break; case 11: this.enterOuterAlt(localctx, 4); { - this.state = 135; + this.state = 137; this.lookupCommand(); } break; case 9: this.enterOuterAlt(localctx, 5); { - this.state = 136; + this.state = 138; this.keepCommand(); } break; case 18: this.enterOuterAlt(localctx, 6); { - this.state = 137; + this.state = 139; this.sortCommand(); } break; case 19: this.enterOuterAlt(localctx, 7); { - this.state = 138; + this.state = 140; this.statsCommand(); } break; case 20: this.enterOuterAlt(localctx, 8); { - this.state = 139; + this.state = 141; this.whereCommand(); } break; case 2: this.enterOuterAlt(localctx, 9); { - this.state = 140; + this.state = 142; this.dropCommand(); } break; case 15: this.enterOuterAlt(localctx, 10); { - this.state = 141; + this.state = 143; this.renameCommand(); } break; case 1: this.enterOuterAlt(localctx, 11); { - this.state = 142; + this.state = 144; this.dissectCommand(); } break; case 7: this.enterOuterAlt(localctx, 12); { - this.state = 143; + this.state = 145; this.grokCommand(); } break; case 3: this.enterOuterAlt(localctx, 13); { - this.state = 144; + this.state = 146; this.enrichCommand(); } break; case 14: this.enterOuterAlt(localctx, 14); { - this.state = 145; + this.state = 147; this.mvExpandCommand(); } break; @@ -675,9 +679,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 148; + this.state = 150; this.match(esql_parser.WHERE); - this.state = 149; + this.state = 151; this.booleanExpression(0); } } @@ -715,7 +719,7 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 179; + this.state = 181; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 6, this._ctx) ) { case 1: @@ -724,9 +728,9 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 152; + this.state = 154; this.match(esql_parser.NOT); - this.state = 153; + this.state = 155; this.booleanExpression(7); } break; @@ -735,7 +739,7 @@ export default class esql_parser extends Parser { localctx = new BooleanDefaultContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 154; + this.state = 156; this.valueExpression(); } break; @@ -744,7 +748,7 @@ export default class esql_parser extends Parser { localctx = new RegexExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 155; + this.state = 157; this.regexBooleanExpression(); } break; @@ -753,41 +757,41 @@ export default class esql_parser extends Parser { localctx = new LogicalInContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 156; - this.valueExpression(); this.state = 158; + this.valueExpression(); + this.state = 160; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===48) { { - this.state = 157; + this.state = 159; this.match(esql_parser.NOT); } } - this.state = 160; + this.state = 162; this.match(esql_parser.IN); - this.state = 161; + this.state = 163; this.match(esql_parser.LP); - this.state = 162; + this.state = 164; this.valueExpression(); - this.state = 167; + this.state = 169; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===38) { { { - this.state = 163; + this.state = 165; this.match(esql_parser.COMMA); - this.state = 164; + this.state = 166; this.valueExpression(); } } - this.state = 169; + this.state = 171; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 170; + this.state = 172; this.match(esql_parser.RP); } break; @@ -796,27 +800,27 @@ export default class esql_parser extends Parser { localctx = new IsNullContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 172; + this.state = 174; this.valueExpression(); - this.state = 173; - this.match(esql_parser.IS); this.state = 175; + this.match(esql_parser.IS); + this.state = 177; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===48) { { - this.state = 174; + this.state = 176; this.match(esql_parser.NOT); } } - this.state = 177; + this.state = 179; this.match(esql_parser.NULL); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 189; + this.state = 191; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 8, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -826,7 +830,7 @@ export default class esql_parser extends Parser { } _prevctx = localctx; { - this.state = 187; + this.state = 189; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 7, this._ctx) ) { case 1: @@ -834,13 +838,13 @@ export default class esql_parser extends Parser { localctx = new LogicalBinaryContext(this, new BooleanExpressionContext(this, _parentctx, _parentState)); (localctx as LogicalBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 181; + this.state = 183; if (!(this.precpred(this._ctx, 4))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 4)"); } - this.state = 182; + this.state = 184; (localctx as LogicalBinaryContext)._operator = this.match(esql_parser.AND); - this.state = 183; + this.state = 185; (localctx as LogicalBinaryContext)._right = this.booleanExpression(5); } break; @@ -849,20 +853,20 @@ export default class esql_parser extends Parser { localctx = new LogicalBinaryContext(this, new BooleanExpressionContext(this, _parentctx, _parentState)); (localctx as LogicalBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 184; + this.state = 186; if (!(this.precpred(this._ctx, 3))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 3)"); } - this.state = 185; + this.state = 187; (localctx as LogicalBinaryContext)._operator = this.match(esql_parser.OR); - this.state = 186; + this.state = 188; (localctx as LogicalBinaryContext)._right = this.booleanExpression(4); } break; } } } - this.state = 191; + this.state = 193; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 8, this._ctx); } @@ -888,48 +892,48 @@ export default class esql_parser extends Parser { this.enterRule(localctx, 12, esql_parser.RULE_regexBooleanExpression); let _la: number; try { - this.state = 206; + this.state = 208; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 11, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 192; - this.valueExpression(); this.state = 194; + this.valueExpression(); + this.state = 196; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===48) { { - this.state = 193; + this.state = 195; this.match(esql_parser.NOT); } } - this.state = 196; + this.state = 198; localctx._kind = this.match(esql_parser.LIKE); - this.state = 197; + this.state = 199; localctx._pattern = this.string_(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 199; - this.valueExpression(); this.state = 201; + this.valueExpression(); + this.state = 203; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===48) { { - this.state = 200; + this.state = 202; this.match(esql_parser.NOT); } } - this.state = 203; + this.state = 205; localctx._kind = this.match(esql_parser.RLIKE); - this.state = 204; + this.state = 206; localctx._pattern = this.string_(); } break; @@ -954,14 +958,14 @@ export default class esql_parser extends Parser { let localctx: ValueExpressionContext = new ValueExpressionContext(this, this._ctx, this.state); this.enterRule(localctx, 14, esql_parser.RULE_valueExpression); try { - this.state = 213; + this.state = 215; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 12, this._ctx) ) { case 1: localctx = new ValueExpressionDefaultContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 208; + this.state = 210; this.operatorExpression(0); } break; @@ -969,11 +973,11 @@ export default class esql_parser extends Parser { localctx = new ComparisonContext(this, localctx); this.enterOuterAlt(localctx, 2); { - this.state = 209; + this.state = 211; (localctx as ComparisonContext)._left = this.operatorExpression(0); - this.state = 210; + this.state = 212; this.comparisonOperator(); - this.state = 211; + this.state = 213; (localctx as ComparisonContext)._right = this.operatorExpression(0); } break; @@ -1013,7 +1017,7 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 219; + this.state = 221; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 13, this._ctx) ) { case 1: @@ -1022,7 +1026,7 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 216; + this.state = 218; this.primaryExpression(0); } break; @@ -1031,7 +1035,7 @@ export default class esql_parser extends Parser { localctx = new ArithmeticUnaryContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 217; + this.state = 219; (localctx as ArithmeticUnaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if(!(_la===63 || _la===64)) { @@ -1041,13 +1045,13 @@ export default class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 218; + this.state = 220; this.operatorExpression(3); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 229; + this.state = 231; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 15, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1057,7 +1061,7 @@ export default class esql_parser extends Parser { } _prevctx = localctx; { - this.state = 227; + this.state = 229; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 14, this._ctx) ) { case 1: @@ -1065,11 +1069,11 @@ export default class esql_parser extends Parser { localctx = new ArithmeticBinaryContext(this, new OperatorExpressionContext(this, _parentctx, _parentState)); (localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 221; + this.state = 223; if (!(this.precpred(this._ctx, 2))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 2)"); } - this.state = 222; + this.state = 224; (localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 65)) & ~0x1F) === 0 && ((1 << (_la - 65)) & 7) !== 0))) { @@ -1079,7 +1083,7 @@ export default class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 223; + this.state = 225; (localctx as ArithmeticBinaryContext)._right = this.operatorExpression(3); } break; @@ -1088,11 +1092,11 @@ export default class esql_parser extends Parser { localctx = new ArithmeticBinaryContext(this, new OperatorExpressionContext(this, _parentctx, _parentState)); (localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 224; + this.state = 226; if (!(this.precpred(this._ctx, 1))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); } - this.state = 225; + this.state = 227; (localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if(!(_la===63 || _la===64)) { @@ -1102,14 +1106,14 @@ export default class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 226; + this.state = 228; (localctx as ArithmeticBinaryContext)._right = this.operatorExpression(2); } break; } } } - this.state = 231; + this.state = 233; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 15, this._ctx); } @@ -1148,7 +1152,7 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 240; + this.state = 242; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 16, this._ctx) ) { case 1: @@ -1157,7 +1161,7 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 233; + this.state = 235; this.constant(); } break; @@ -1166,7 +1170,7 @@ export default class esql_parser extends Parser { localctx = new DereferenceContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 234; + this.state = 236; this.qualifiedName(); } break; @@ -1175,7 +1179,7 @@ export default class esql_parser extends Parser { localctx = new FunctionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 235; + this.state = 237; this.functionExpression(); } break; @@ -1184,17 +1188,17 @@ export default class esql_parser extends Parser { localctx = new ParenthesizedExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 236; + this.state = 238; this.match(esql_parser.LP); - this.state = 237; + this.state = 239; this.booleanExpression(0); - this.state = 238; + this.state = 240; this.match(esql_parser.RP); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 247; + this.state = 249; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 17, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1207,18 +1211,18 @@ export default class esql_parser extends Parser { { localctx = new InlineCastContext(this, new PrimaryExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_primaryExpression); - this.state = 242; + this.state = 244; if (!(this.precpred(this._ctx, 1))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); } - this.state = 243; + this.state = 245; this.match(esql_parser.CAST_OP); - this.state = 244; + this.state = 246; this.dataType(); } } } - this.state = 249; + this.state = 251; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 17, this._ctx); } @@ -1246,16 +1250,16 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 250; + this.state = 252; this.identifier(); - this.state = 251; + this.state = 253; this.match(esql_parser.LP); - this.state = 261; + this.state = 263; this._errHandler.sync(this); switch (this._input.LA(1)) { case 65: { - this.state = 252; + this.state = 254; this.match(esql_parser.ASTERISK); } break; @@ -1271,25 +1275,26 @@ export default class esql_parser extends Parser { case 63: case 64: case 68: - case 70: + case 69: case 71: + case 72: { { - this.state = 253; + this.state = 255; this.booleanExpression(0); - this.state = 258; + this.state = 260; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===38) { { { - this.state = 254; + this.state = 256; this.match(esql_parser.COMMA); - this.state = 255; + this.state = 257; this.booleanExpression(0); } } - this.state = 260; + this.state = 262; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1301,7 +1306,7 @@ export default class esql_parser extends Parser { default: break; } - this.state = 263; + this.state = 265; this.match(esql_parser.RP); } } @@ -1327,7 +1332,7 @@ export default class esql_parser extends Parser { localctx = new ToDataTypeContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 265; + this.state = 267; this.identifier(); } } @@ -1352,9 +1357,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 267; + this.state = 269; this.match(esql_parser.ROW); - this.state = 268; + this.state = 270; this.fields(); } } @@ -1380,23 +1385,23 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 270; + this.state = 272; this.field(); - this.state = 275; + this.state = 277; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 20, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 271; + this.state = 273; this.match(esql_parser.COMMA); - this.state = 272; + this.state = 274; this.field(); } } } - this.state = 277; + this.state = 279; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 20, this._ctx); } @@ -1421,24 +1426,24 @@ export default class esql_parser extends Parser { let localctx: FieldContext = new FieldContext(this, this._ctx, this.state); this.enterRule(localctx, 28, esql_parser.RULE_field); try { - this.state = 283; + this.state = 285; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 278; + this.state = 280; this.booleanExpression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 279; + this.state = 281; this.qualifiedName(); - this.state = 280; + this.state = 282; this.match(esql_parser.ASSIGN); - this.state = 281; + this.state = 283; this.booleanExpression(0); } break; @@ -1466,34 +1471,34 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 285; + this.state = 287; this.match(esql_parser.FROM); - this.state = 286; + this.state = 288; this.indexIdentifier(); - this.state = 291; + this.state = 293; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 22, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 287; + this.state = 289; this.match(esql_parser.COMMA); - this.state = 288; + this.state = 290; this.indexIdentifier(); } } } - this.state = 293; + this.state = 295; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 22, this._ctx); } - this.state = 295; + this.state = 297; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 23, this._ctx) ) { case 1: { - this.state = 294; + this.state = 296; this.metadata(); } break; @@ -1521,7 +1526,7 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 297; + this.state = 299; this.match(esql_parser.INDEX_UNQUOTED_IDENTIFIER); } } @@ -1544,20 +1549,20 @@ export default class esql_parser extends Parser { let localctx: MetadataContext = new MetadataContext(this, this._ctx, this.state); this.enterRule(localctx, 34, esql_parser.RULE_metadata); try { - this.state = 301; + this.state = 303; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 75: + case 76: this.enterOuterAlt(localctx, 1); { - this.state = 299; + this.state = 301; this.metadataOption(); } break; - case 68: + case 69: this.enterOuterAlt(localctx, 2); { - this.state = 300; + this.state = 302; this.deprecated_metadata(); } break; @@ -1587,25 +1592,25 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 303; + this.state = 305; this.match(esql_parser.METADATA); - this.state = 304; + this.state = 306; this.indexIdentifier(); - this.state = 309; + this.state = 311; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 305; + this.state = 307; this.match(esql_parser.COMMA); - this.state = 306; + this.state = 308; this.indexIdentifier(); } } } - this.state = 311; + this.state = 313; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); } @@ -1632,11 +1637,11 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 312; + this.state = 314; this.match(esql_parser.OPENING_BRACKET); - this.state = 313; + this.state = 315; this.metadataOption(); - this.state = 314; + this.state = 316; this.match(esql_parser.CLOSING_BRACKET); } } @@ -1662,46 +1667,46 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 316; + this.state = 318; this.match(esql_parser.METRICS); - this.state = 317; + this.state = 319; this.indexIdentifier(); - this.state = 322; + this.state = 324; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 26, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 318; + this.state = 320; this.match(esql_parser.COMMA); - this.state = 319; + this.state = 321; this.indexIdentifier(); } } } - this.state = 324; + this.state = 326; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 26, this._ctx); } - this.state = 326; + this.state = 328; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 27, this._ctx) ) { case 1: { - this.state = 325; + this.state = 327; localctx._aggregates = this.fields(); } break; } - this.state = 330; + this.state = 332; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 28, this._ctx) ) { case 1: { - this.state = 328; + this.state = 330; this.match(esql_parser.BY); - this.state = 329; + this.state = 331; localctx._grouping = this.fields(); } break; @@ -1729,9 +1734,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 332; + this.state = 334; this.match(esql_parser.EVAL); - this.state = 333; + this.state = 335; this.fields(); } } @@ -1756,26 +1761,26 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 335; - this.match(esql_parser.STATS); this.state = 337; + this.match(esql_parser.STATS); + this.state = 339; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 29, this._ctx) ) { case 1: { - this.state = 336; + this.state = 338; localctx._stats = this.fields(); } break; } - this.state = 341; + this.state = 343; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 30, this._ctx) ) { case 1: { - this.state = 339; + this.state = 341; this.match(esql_parser.BY); - this.state = 340; + this.state = 342; localctx._grouping = this.fields(); } break; @@ -1803,18 +1808,18 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 343; + this.state = 345; this.match(esql_parser.INLINESTATS); - this.state = 344; + this.state = 346; localctx._stats = this.fields(); - this.state = 347; + this.state = 349; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 31, this._ctx) ) { case 1: { - this.state = 345; + this.state = 347; this.match(esql_parser.BY); - this.state = 346; + this.state = 348; localctx._grouping = this.fields(); } break; @@ -1843,23 +1848,23 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 349; + this.state = 351; this.identifier(); - this.state = 354; + this.state = 356; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 350; + this.state = 352; this.match(esql_parser.DOT); - this.state = 351; + this.state = 353; this.identifier(); } } } - this.state = 356; + this.state = 358; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); } @@ -1887,23 +1892,23 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 357; + this.state = 359; this.identifierPattern(); - this.state = 362; + this.state = 364; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 33, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 358; + this.state = 360; this.match(esql_parser.DOT); - this.state = 359; + this.state = 361; this.identifierPattern(); } } } - this.state = 364; + this.state = 366; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 33, this._ctx); } @@ -1931,23 +1936,23 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 365; + this.state = 367; this.qualifiedNamePattern(); - this.state = 370; + this.state = 372; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 34, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 366; + this.state = 368; this.match(esql_parser.COMMA); - this.state = 367; + this.state = 369; this.qualifiedNamePattern(); } } } - this.state = 372; + this.state = 374; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 34, this._ctx); } @@ -1975,9 +1980,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 373; + this.state = 375; _la = this._input.LA(1); - if(!(_la===70 || _la===71)) { + if(!(_la===71 || _la===72)) { this._errHandler.recoverInline(this); } else { @@ -2007,7 +2012,7 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 375; + this.state = 377; this.match(esql_parser.ID_PATTERN); } } @@ -2031,14 +2036,14 @@ export default class esql_parser extends Parser { this.enterRule(localctx, 58, esql_parser.RULE_constant); let _la: number; try { - this.state = 419; + this.state = 421; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 38, this._ctx) ) { case 1: localctx = new NullLiteralContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 377; + this.state = 379; this.match(esql_parser.NULL); } break; @@ -2046,9 +2051,9 @@ export default class esql_parser extends Parser { localctx = new QualifiedIntegerLiteralContext(this, localctx); this.enterOuterAlt(localctx, 2); { - this.state = 378; + this.state = 380; this.integerValue(); - this.state = 379; + this.state = 381; this.match(esql_parser.UNQUOTED_IDENTIFIER); } break; @@ -2056,7 +2061,7 @@ export default class esql_parser extends Parser { localctx = new DecimalLiteralContext(this, localctx); this.enterOuterAlt(localctx, 3); { - this.state = 381; + this.state = 383; this.decimalValue(); } break; @@ -2064,7 +2069,7 @@ export default class esql_parser extends Parser { localctx = new IntegerLiteralContext(this, localctx); this.enterOuterAlt(localctx, 4); { - this.state = 382; + this.state = 384; this.integerValue(); } break; @@ -2072,23 +2077,23 @@ export default class esql_parser extends Parser { localctx = new BooleanLiteralContext(this, localctx); this.enterOuterAlt(localctx, 5); { - this.state = 383; + this.state = 385; this.booleanValue(); } break; case 6: - localctx = new InputParamContext(this, localctx); + localctx = new InputParamsContext(this, localctx); this.enterOuterAlt(localctx, 6); { - this.state = 384; - this.match(esql_parser.PARAM); + this.state = 386; + this.params(); } break; case 7: localctx = new StringLiteralContext(this, localctx); this.enterOuterAlt(localctx, 7); { - this.state = 385; + this.state = 387; this.string_(); } break; @@ -2096,27 +2101,27 @@ export default class esql_parser extends Parser { localctx = new NumericArrayLiteralContext(this, localctx); this.enterOuterAlt(localctx, 8); { - this.state = 386; + this.state = 388; this.match(esql_parser.OPENING_BRACKET); - this.state = 387; + this.state = 389; this.numericValue(); - this.state = 392; + this.state = 394; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===38) { { { - this.state = 388; + this.state = 390; this.match(esql_parser.COMMA); - this.state = 389; + this.state = 391; this.numericValue(); } } - this.state = 394; + this.state = 396; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 395; + this.state = 397; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2124,27 +2129,27 @@ export default class esql_parser extends Parser { localctx = new BooleanArrayLiteralContext(this, localctx); this.enterOuterAlt(localctx, 9); { - this.state = 397; + this.state = 399; this.match(esql_parser.OPENING_BRACKET); - this.state = 398; + this.state = 400; this.booleanValue(); - this.state = 403; + this.state = 405; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===38) { { { - this.state = 399; + this.state = 401; this.match(esql_parser.COMMA); - this.state = 400; + this.state = 402; this.booleanValue(); } } - this.state = 405; + this.state = 407; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 406; + this.state = 408; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2152,27 +2157,27 @@ export default class esql_parser extends Parser { localctx = new StringArrayLiteralContext(this, localctx); this.enterOuterAlt(localctx, 10); { - this.state = 408; + this.state = 410; this.match(esql_parser.OPENING_BRACKET); - this.state = 409; + this.state = 411; this.string_(); - this.state = 414; + this.state = 416; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===38) { { { - this.state = 410; + this.state = 412; this.match(esql_parser.COMMA); - this.state = 411; + this.state = 413; this.string_(); } } - this.state = 416; + this.state = 418; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 417; + this.state = 419; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2193,15 +2198,57 @@ export default class esql_parser extends Parser { return localctx; } // @RuleVersion(0) + public params(): ParamsContext { + let localctx: ParamsContext = new ParamsContext(this, this._ctx, this.state); + this.enterRule(localctx, 60, esql_parser.RULE_params); + try { + this.state = 425; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 52: + localctx = new InputParamContext(this, localctx); + this.enterOuterAlt(localctx, 1); + { + this.state = 423; + this.match(esql_parser.PARAM); + } + break; + case 68: + localctx = new InputNamedOrPositionalParamContext(this, localctx); + this.enterOuterAlt(localctx, 2); + { + this.state = 424; + this.match(esql_parser.NAMED_OR_POSITIONAL_PARAM); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) public limitCommand(): LimitCommandContext { let localctx: LimitCommandContext = new LimitCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 60, esql_parser.RULE_limitCommand); + this.enterRule(localctx, 62, esql_parser.RULE_limitCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 421; + this.state = 427; this.match(esql_parser.LIMIT); - this.state = 422; + this.state = 428; this.match(esql_parser.INTEGER_LITERAL); } } @@ -2222,32 +2269,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public sortCommand(): SortCommandContext { let localctx: SortCommandContext = new SortCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 62, esql_parser.RULE_sortCommand); + this.enterRule(localctx, 64, esql_parser.RULE_sortCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 424; + this.state = 430; this.match(esql_parser.SORT); - this.state = 425; + this.state = 431; this.orderExpression(); - this.state = 430; + this.state = 436; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 426; + this.state = 432; this.match(esql_parser.COMMA); - this.state = 427; + this.state = 433; this.orderExpression(); } } } - this.state = 432; + this.state = 438; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); } } } @@ -2268,19 +2315,19 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public orderExpression(): OrderExpressionContext { let localctx: OrderExpressionContext = new OrderExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 64, esql_parser.RULE_orderExpression); + this.enterRule(localctx, 66, esql_parser.RULE_orderExpression); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 433; + this.state = 439; this.booleanExpression(0); - this.state = 435; + this.state = 441; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 40, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 41, this._ctx) ) { case 1: { - this.state = 434; + this.state = 440; localctx._ordering = this._input.LT(1); _la = this._input.LA(1); if(!(_la===35 || _la===39)) { @@ -2293,14 +2340,14 @@ export default class esql_parser extends Parser { } break; } - this.state = 439; + this.state = 445; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 41, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 42, this._ctx) ) { case 1: { - this.state = 437; + this.state = 443; this.match(esql_parser.NULLS); - this.state = 438; + this.state = 444; localctx._nullOrdering = this._input.LT(1); _la = this._input.LA(1); if(!(_la===42 || _la===43)) { @@ -2332,13 +2379,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public keepCommand(): KeepCommandContext { let localctx: KeepCommandContext = new KeepCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 66, esql_parser.RULE_keepCommand); + this.enterRule(localctx, 68, esql_parser.RULE_keepCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 441; + this.state = 447; this.match(esql_parser.KEEP); - this.state = 442; + this.state = 448; this.qualifiedNamePatterns(); } } @@ -2359,13 +2406,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public dropCommand(): DropCommandContext { let localctx: DropCommandContext = new DropCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 68, esql_parser.RULE_dropCommand); + this.enterRule(localctx, 70, esql_parser.RULE_dropCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 444; + this.state = 450; this.match(esql_parser.DROP); - this.state = 445; + this.state = 451; this.qualifiedNamePatterns(); } } @@ -2386,32 +2433,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public renameCommand(): RenameCommandContext { let localctx: RenameCommandContext = new RenameCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 70, esql_parser.RULE_renameCommand); + this.enterRule(localctx, 72, esql_parser.RULE_renameCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 447; + this.state = 453; this.match(esql_parser.RENAME); - this.state = 448; + this.state = 454; this.renameClause(); - this.state = 453; + this.state = 459; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 42, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 43, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 449; + this.state = 455; this.match(esql_parser.COMMA); - this.state = 450; + this.state = 456; this.renameClause(); } } } - this.state = 455; + this.state = 461; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 42, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 43, this._ctx); } } } @@ -2432,15 +2479,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public renameClause(): RenameClauseContext { let localctx: RenameClauseContext = new RenameClauseContext(this, this._ctx, this.state); - this.enterRule(localctx, 72, esql_parser.RULE_renameClause); + this.enterRule(localctx, 74, esql_parser.RULE_renameClause); try { this.enterOuterAlt(localctx, 1); { - this.state = 456; + this.state = 462; localctx._oldName = this.qualifiedNamePattern(); - this.state = 457; + this.state = 463; this.match(esql_parser.AS); - this.state = 458; + this.state = 464; localctx._newName = this.qualifiedNamePattern(); } } @@ -2461,22 +2508,22 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public dissectCommand(): DissectCommandContext { let localctx: DissectCommandContext = new DissectCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 74, esql_parser.RULE_dissectCommand); + this.enterRule(localctx, 76, esql_parser.RULE_dissectCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 460; + this.state = 466; this.match(esql_parser.DISSECT); - this.state = 461; + this.state = 467; this.primaryExpression(0); - this.state = 462; + this.state = 468; this.string_(); - this.state = 464; + this.state = 470; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 44, this._ctx) ) { case 1: { - this.state = 463; + this.state = 469; this.commandOptions(); } break; @@ -2500,15 +2547,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public grokCommand(): GrokCommandContext { let localctx: GrokCommandContext = new GrokCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 76, esql_parser.RULE_grokCommand); + this.enterRule(localctx, 78, esql_parser.RULE_grokCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 466; + this.state = 472; this.match(esql_parser.GROK); - this.state = 467; + this.state = 473; this.primaryExpression(0); - this.state = 468; + this.state = 474; this.string_(); } } @@ -2529,13 +2576,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public mvExpandCommand(): MvExpandCommandContext { let localctx: MvExpandCommandContext = new MvExpandCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 78, esql_parser.RULE_mvExpandCommand); + this.enterRule(localctx, 80, esql_parser.RULE_mvExpandCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 470; + this.state = 476; this.match(esql_parser.MV_EXPAND); - this.state = 471; + this.state = 477; this.qualifiedName(); } } @@ -2556,30 +2603,30 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public commandOptions(): CommandOptionsContext { let localctx: CommandOptionsContext = new CommandOptionsContext(this, this._ctx, this.state); - this.enterRule(localctx, 80, esql_parser.RULE_commandOptions); + this.enterRule(localctx, 82, esql_parser.RULE_commandOptions); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 473; + this.state = 479; this.commandOption(); - this.state = 478; + this.state = 484; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 45, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 474; + this.state = 480; this.match(esql_parser.COMMA); - this.state = 475; + this.state = 481; this.commandOption(); } } } - this.state = 480; + this.state = 486; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 45, this._ctx); } } } @@ -2600,15 +2647,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public commandOption(): CommandOptionContext { let localctx: CommandOptionContext = new CommandOptionContext(this, this._ctx, this.state); - this.enterRule(localctx, 82, esql_parser.RULE_commandOption); + this.enterRule(localctx, 84, esql_parser.RULE_commandOption); try { this.enterOuterAlt(localctx, 1); { - this.state = 481; + this.state = 487; this.identifier(); - this.state = 482; + this.state = 488; this.match(esql_parser.ASSIGN); - this.state = 483; + this.state = 489; this.constant(); } } @@ -2629,12 +2676,12 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public booleanValue(): BooleanValueContext { let localctx: BooleanValueContext = new BooleanValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 84, esql_parser.RULE_booleanValue); + this.enterRule(localctx, 86, esql_parser.RULE_booleanValue); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 485; + this.state = 491; _la = this._input.LA(1); if(!(_la===41 || _la===55)) { this._errHandler.recoverInline(this); @@ -2662,22 +2709,22 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public numericValue(): NumericValueContext { let localctx: NumericValueContext = new NumericValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 86, esql_parser.RULE_numericValue); + this.enterRule(localctx, 88, esql_parser.RULE_numericValue); try { - this.state = 489; + this.state = 495; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 45, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 46, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 487; + this.state = 493; this.decimalValue(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 488; + this.state = 494; this.integerValue(); } break; @@ -2700,17 +2747,17 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public decimalValue(): DecimalValueContext { let localctx: DecimalValueContext = new DecimalValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 88, esql_parser.RULE_decimalValue); + this.enterRule(localctx, 90, esql_parser.RULE_decimalValue); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 492; + this.state = 498; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===63 || _la===64) { { - this.state = 491; + this.state = 497; _la = this._input.LA(1); if(!(_la===63 || _la===64)) { this._errHandler.recoverInline(this); @@ -2722,7 +2769,7 @@ export default class esql_parser extends Parser { } } - this.state = 494; + this.state = 500; this.match(esql_parser.DECIMAL_LITERAL); } } @@ -2743,17 +2790,17 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public integerValue(): IntegerValueContext { let localctx: IntegerValueContext = new IntegerValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 90, esql_parser.RULE_integerValue); + this.enterRule(localctx, 92, esql_parser.RULE_integerValue); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 497; + this.state = 503; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===63 || _la===64) { { - this.state = 496; + this.state = 502; _la = this._input.LA(1); if(!(_la===63 || _la===64)) { this._errHandler.recoverInline(this); @@ -2765,7 +2812,7 @@ export default class esql_parser extends Parser { } } - this.state = 499; + this.state = 505; this.match(esql_parser.INTEGER_LITERAL); } } @@ -2786,11 +2833,11 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public string_(): StringContext { let localctx: StringContext = new StringContext(this, this._ctx, this.state); - this.enterRule(localctx, 92, esql_parser.RULE_string); + this.enterRule(localctx, 94, esql_parser.RULE_string); try { this.enterOuterAlt(localctx, 1); { - this.state = 501; + this.state = 507; this.match(esql_parser.QUOTED_STRING); } } @@ -2811,12 +2858,12 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public comparisonOperator(): ComparisonOperatorContext { let localctx: ComparisonOperatorContext = new ComparisonOperatorContext(this, this._ctx, this.state); - this.enterRule(localctx, 94, esql_parser.RULE_comparisonOperator); + this.enterRule(localctx, 96, esql_parser.RULE_comparisonOperator); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 503; + this.state = 509; _la = this._input.LA(1); if(!(((((_la - 56)) & ~0x1F) === 0 && ((1 << (_la - 56)) & 125) !== 0))) { this._errHandler.recoverInline(this); @@ -2844,13 +2891,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public explainCommand(): ExplainCommandContext { let localctx: ExplainCommandContext = new ExplainCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 96, esql_parser.RULE_explainCommand); + this.enterRule(localctx, 98, esql_parser.RULE_explainCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 505; + this.state = 511; this.match(esql_parser.EXPLAIN); - this.state = 506; + this.state = 512; this.subqueryExpression(); } } @@ -2871,15 +2918,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public subqueryExpression(): SubqueryExpressionContext { let localctx: SubqueryExpressionContext = new SubqueryExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 98, esql_parser.RULE_subqueryExpression); + this.enterRule(localctx, 100, esql_parser.RULE_subqueryExpression); try { this.enterOuterAlt(localctx, 1); { - this.state = 508; + this.state = 514; this.match(esql_parser.OPENING_BRACKET); - this.state = 509; + this.state = 515; this.query(0); - this.state = 510; + this.state = 516; this.match(esql_parser.CLOSING_BRACKET); } } @@ -2900,14 +2947,14 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public showCommand(): ShowCommandContext { let localctx: ShowCommandContext = new ShowCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 100, esql_parser.RULE_showCommand); + this.enterRule(localctx, 102, esql_parser.RULE_showCommand); try { localctx = new ShowInfoContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 512; + this.state = 518; this.match(esql_parser.SHOW); - this.state = 513; + this.state = 519; this.match(esql_parser.INFO); } } @@ -2928,14 +2975,14 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public metaCommand(): MetaCommandContext { let localctx: MetaCommandContext = new MetaCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 102, esql_parser.RULE_metaCommand); + this.enterRule(localctx, 104, esql_parser.RULE_metaCommand); try { localctx = new MetaFunctionsContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 515; + this.state = 521; this.match(esql_parser.META); - this.state = 516; + this.state = 522; this.match(esql_parser.FUNCTIONS); } } @@ -2956,53 +3003,53 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public enrichCommand(): EnrichCommandContext { let localctx: EnrichCommandContext = new EnrichCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 104, esql_parser.RULE_enrichCommand); + this.enterRule(localctx, 106, esql_parser.RULE_enrichCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 518; + this.state = 524; this.match(esql_parser.ENRICH); - this.state = 519; + this.state = 525; localctx._policyName = this.match(esql_parser.ENRICH_POLICY_NAME); - this.state = 522; + this.state = 528; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 48, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 49, this._ctx) ) { case 1: { - this.state = 520; + this.state = 526; this.match(esql_parser.ON); - this.state = 521; + this.state = 527; localctx._matchField = this.qualifiedNamePattern(); } break; } - this.state = 533; + this.state = 539; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 50, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 51, this._ctx) ) { case 1: { - this.state = 524; + this.state = 530; this.match(esql_parser.WITH); - this.state = 525; + this.state = 531; this.enrichWithClause(); - this.state = 530; + this.state = 536; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 49, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 50, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 526; + this.state = 532; this.match(esql_parser.COMMA); - this.state = 527; + this.state = 533; this.enrichWithClause(); } } } - this.state = 532; + this.state = 538; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 49, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 50, this._ctx); } } break; @@ -3026,23 +3073,23 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public enrichWithClause(): EnrichWithClauseContext { let localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this, this._ctx, this.state); - this.enterRule(localctx, 106, esql_parser.RULE_enrichWithClause); + this.enterRule(localctx, 108, esql_parser.RULE_enrichWithClause); try { this.enterOuterAlt(localctx, 1); { - this.state = 538; + this.state = 544; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 51, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 52, this._ctx) ) { case 1: { - this.state = 535; + this.state = 541; localctx._newName = this.qualifiedNamePattern(); - this.state = 536; + this.state = 542; this.match(esql_parser.ASSIGN); } break; } - this.state = 540; + this.state = 546; localctx._enrichField = this.qualifiedNamePattern(); } } @@ -3063,17 +3110,17 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public lookupCommand(): LookupCommandContext { let localctx: LookupCommandContext = new LookupCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 108, esql_parser.RULE_lookupCommand); + this.enterRule(localctx, 110, esql_parser.RULE_lookupCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 542; + this.state = 548; this.match(esql_parser.LOOKUP); - this.state = 543; + this.state = 549; localctx._tableName = this.match(esql_parser.INDEX_UNQUOTED_IDENTIFIER); - this.state = 544; + this.state = 550; this.match(esql_parser.ON); - this.state = 545; + this.state = 551; localctx._matchFields = this.qualifiedNamePatterns(); } } @@ -3138,7 +3185,7 @@ export default class esql_parser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,123,548,2,0,7,0, + public static readonly _serializedATN: number[] = [4,1,124,554,2,0,7,0, 2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9, 2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2, 17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24, @@ -3146,177 +3193,179 @@ export default class esql_parser extends Parser { 31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38, 2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7,45,2, 46,7,46,2,47,7,47,2,48,7,48,2,49,7,49,2,50,7,50,2,51,7,51,2,52,7,52,2,53, - 7,53,2,54,7,54,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,5,1,120,8,1,10,1,12, - 1,123,9,1,1,2,1,2,1,2,1,2,1,2,1,2,3,2,131,8,2,1,3,1,3,1,3,1,3,1,3,1,3,1, - 3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,3,3,147,8,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1, - 5,1,5,1,5,3,5,159,8,5,1,5,1,5,1,5,1,5,1,5,5,5,166,8,5,10,5,12,5,169,9,5, - 1,5,1,5,1,5,1,5,1,5,3,5,176,8,5,1,5,1,5,3,5,180,8,5,1,5,1,5,1,5,1,5,1,5, - 1,5,5,5,188,8,5,10,5,12,5,191,9,5,1,6,1,6,3,6,195,8,6,1,6,1,6,1,6,1,6,1, - 6,3,6,202,8,6,1,6,1,6,1,6,3,6,207,8,6,1,7,1,7,1,7,1,7,1,7,3,7,214,8,7,1, - 8,1,8,1,8,1,8,3,8,220,8,8,1,8,1,8,1,8,1,8,1,8,1,8,5,8,228,8,8,10,8,12,8, - 231,9,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,3,9,241,8,9,1,9,1,9,1,9,5,9,246, - 8,9,10,9,12,9,249,9,9,1,10,1,10,1,10,1,10,1,10,1,10,5,10,257,8,10,10,10, - 12,10,260,9,10,3,10,262,8,10,1,10,1,10,1,11,1,11,1,12,1,12,1,12,1,13,1, - 13,1,13,5,13,274,8,13,10,13,12,13,277,9,13,1,14,1,14,1,14,1,14,1,14,3,14, - 284,8,14,1,15,1,15,1,15,1,15,5,15,290,8,15,10,15,12,15,293,9,15,1,15,3, - 15,296,8,15,1,16,1,16,1,17,1,17,3,17,302,8,17,1,18,1,18,1,18,1,18,5,18, - 308,8,18,10,18,12,18,311,9,18,1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,5, - 20,321,8,20,10,20,12,20,324,9,20,1,20,3,20,327,8,20,1,20,1,20,3,20,331, - 8,20,1,21,1,21,1,21,1,22,1,22,3,22,338,8,22,1,22,1,22,3,22,342,8,22,1,23, - 1,23,1,23,1,23,3,23,348,8,23,1,24,1,24,1,24,5,24,353,8,24,10,24,12,24,356, - 9,24,1,25,1,25,1,25,5,25,361,8,25,10,25,12,25,364,9,25,1,26,1,26,1,26,5, - 26,369,8,26,10,26,12,26,372,9,26,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,29, - 1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,391,8,29,10,29,12,29, - 394,9,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,402,8,29,10,29,12,29,405,9, - 29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,413,8,29,10,29,12,29,416,9,29,1,29, - 1,29,3,29,420,8,29,1,30,1,30,1,30,1,31,1,31,1,31,1,31,5,31,429,8,31,10, - 31,12,31,432,9,31,1,32,1,32,3,32,436,8,32,1,32,1,32,3,32,440,8,32,1,33, - 1,33,1,33,1,34,1,34,1,34,1,35,1,35,1,35,1,35,5,35,452,8,35,10,35,12,35, - 455,9,35,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,37,3,37,465,8,37,1,38,1,38, - 1,38,1,38,1,39,1,39,1,39,1,40,1,40,1,40,5,40,477,8,40,10,40,12,40,480,9, - 40,1,41,1,41,1,41,1,41,1,42,1,42,1,43,1,43,3,43,490,8,43,1,44,3,44,493, - 8,44,1,44,1,44,1,45,3,45,498,8,45,1,45,1,45,1,46,1,46,1,47,1,47,1,48,1, - 48,1,48,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,51,1,51,1,51,1,52,1,52,1,52, - 1,52,3,52,523,8,52,1,52,1,52,1,52,1,52,5,52,529,8,52,10,52,12,52,532,9, - 52,3,52,534,8,52,1,53,1,53,1,53,3,53,539,8,53,1,53,1,53,1,54,1,54,1,54, - 1,54,1,54,1,54,0,4,2,10,16,18,55,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28, - 30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76, - 78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,0,7,1,0,63,64,1,0, - 65,67,1,0,70,71,2,0,35,35,39,39,1,0,42,43,2,0,41,41,55,55,2,0,56,56,58, - 62,574,0,110,1,0,0,0,2,113,1,0,0,0,4,130,1,0,0,0,6,146,1,0,0,0,8,148,1, - 0,0,0,10,179,1,0,0,0,12,206,1,0,0,0,14,213,1,0,0,0,16,219,1,0,0,0,18,240, - 1,0,0,0,20,250,1,0,0,0,22,265,1,0,0,0,24,267,1,0,0,0,26,270,1,0,0,0,28, - 283,1,0,0,0,30,285,1,0,0,0,32,297,1,0,0,0,34,301,1,0,0,0,36,303,1,0,0,0, - 38,312,1,0,0,0,40,316,1,0,0,0,42,332,1,0,0,0,44,335,1,0,0,0,46,343,1,0, - 0,0,48,349,1,0,0,0,50,357,1,0,0,0,52,365,1,0,0,0,54,373,1,0,0,0,56,375, - 1,0,0,0,58,419,1,0,0,0,60,421,1,0,0,0,62,424,1,0,0,0,64,433,1,0,0,0,66, - 441,1,0,0,0,68,444,1,0,0,0,70,447,1,0,0,0,72,456,1,0,0,0,74,460,1,0,0,0, - 76,466,1,0,0,0,78,470,1,0,0,0,80,473,1,0,0,0,82,481,1,0,0,0,84,485,1,0, - 0,0,86,489,1,0,0,0,88,492,1,0,0,0,90,497,1,0,0,0,92,501,1,0,0,0,94,503, - 1,0,0,0,96,505,1,0,0,0,98,508,1,0,0,0,100,512,1,0,0,0,102,515,1,0,0,0,104, - 518,1,0,0,0,106,538,1,0,0,0,108,542,1,0,0,0,110,111,3,2,1,0,111,112,5,0, - 0,1,112,1,1,0,0,0,113,114,6,1,-1,0,114,115,3,4,2,0,115,121,1,0,0,0,116, - 117,10,1,0,0,117,118,5,29,0,0,118,120,3,6,3,0,119,116,1,0,0,0,120,123,1, - 0,0,0,121,119,1,0,0,0,121,122,1,0,0,0,122,3,1,0,0,0,123,121,1,0,0,0,124, - 131,3,96,48,0,125,131,3,30,15,0,126,131,3,24,12,0,127,131,3,40,20,0,128, - 131,3,100,50,0,129,131,3,102,51,0,130,124,1,0,0,0,130,125,1,0,0,0,130,126, - 1,0,0,0,130,127,1,0,0,0,130,128,1,0,0,0,130,129,1,0,0,0,131,5,1,0,0,0,132, - 147,3,42,21,0,133,147,3,46,23,0,134,147,3,60,30,0,135,147,3,108,54,0,136, - 147,3,66,33,0,137,147,3,62,31,0,138,147,3,44,22,0,139,147,3,8,4,0,140,147, - 3,68,34,0,141,147,3,70,35,0,142,147,3,74,37,0,143,147,3,76,38,0,144,147, - 3,104,52,0,145,147,3,78,39,0,146,132,1,0,0,0,146,133,1,0,0,0,146,134,1, - 0,0,0,146,135,1,0,0,0,146,136,1,0,0,0,146,137,1,0,0,0,146,138,1,0,0,0,146, - 139,1,0,0,0,146,140,1,0,0,0,146,141,1,0,0,0,146,142,1,0,0,0,146,143,1,0, - 0,0,146,144,1,0,0,0,146,145,1,0,0,0,147,7,1,0,0,0,148,149,5,20,0,0,149, - 150,3,10,5,0,150,9,1,0,0,0,151,152,6,5,-1,0,152,153,5,48,0,0,153,180,3, - 10,5,7,154,180,3,14,7,0,155,180,3,12,6,0,156,158,3,14,7,0,157,159,5,48, - 0,0,158,157,1,0,0,0,158,159,1,0,0,0,159,160,1,0,0,0,160,161,5,45,0,0,161, - 162,5,44,0,0,162,167,3,14,7,0,163,164,5,38,0,0,164,166,3,14,7,0,165,163, - 1,0,0,0,166,169,1,0,0,0,167,165,1,0,0,0,167,168,1,0,0,0,168,170,1,0,0,0, - 169,167,1,0,0,0,170,171,5,54,0,0,171,180,1,0,0,0,172,173,3,14,7,0,173,175, - 5,46,0,0,174,176,5,48,0,0,175,174,1,0,0,0,175,176,1,0,0,0,176,177,1,0,0, - 0,177,178,5,49,0,0,178,180,1,0,0,0,179,151,1,0,0,0,179,154,1,0,0,0,179, - 155,1,0,0,0,179,156,1,0,0,0,179,172,1,0,0,0,180,189,1,0,0,0,181,182,10, - 4,0,0,182,183,5,34,0,0,183,188,3,10,5,5,184,185,10,3,0,0,185,186,5,51,0, - 0,186,188,3,10,5,4,187,181,1,0,0,0,187,184,1,0,0,0,188,191,1,0,0,0,189, - 187,1,0,0,0,189,190,1,0,0,0,190,11,1,0,0,0,191,189,1,0,0,0,192,194,3,14, - 7,0,193,195,5,48,0,0,194,193,1,0,0,0,194,195,1,0,0,0,195,196,1,0,0,0,196, - 197,5,47,0,0,197,198,3,92,46,0,198,207,1,0,0,0,199,201,3,14,7,0,200,202, - 5,48,0,0,201,200,1,0,0,0,201,202,1,0,0,0,202,203,1,0,0,0,203,204,5,53,0, - 0,204,205,3,92,46,0,205,207,1,0,0,0,206,192,1,0,0,0,206,199,1,0,0,0,207, - 13,1,0,0,0,208,214,3,16,8,0,209,210,3,16,8,0,210,211,3,94,47,0,211,212, - 3,16,8,0,212,214,1,0,0,0,213,208,1,0,0,0,213,209,1,0,0,0,214,15,1,0,0,0, - 215,216,6,8,-1,0,216,220,3,18,9,0,217,218,7,0,0,0,218,220,3,16,8,3,219, - 215,1,0,0,0,219,217,1,0,0,0,220,229,1,0,0,0,221,222,10,2,0,0,222,223,7, - 1,0,0,223,228,3,16,8,3,224,225,10,1,0,0,225,226,7,0,0,0,226,228,3,16,8, - 2,227,221,1,0,0,0,227,224,1,0,0,0,228,231,1,0,0,0,229,227,1,0,0,0,229,230, - 1,0,0,0,230,17,1,0,0,0,231,229,1,0,0,0,232,233,6,9,-1,0,233,241,3,58,29, - 0,234,241,3,48,24,0,235,241,3,20,10,0,236,237,5,44,0,0,237,238,3,10,5,0, - 238,239,5,54,0,0,239,241,1,0,0,0,240,232,1,0,0,0,240,234,1,0,0,0,240,235, - 1,0,0,0,240,236,1,0,0,0,241,247,1,0,0,0,242,243,10,1,0,0,243,244,5,37,0, - 0,244,246,3,22,11,0,245,242,1,0,0,0,246,249,1,0,0,0,247,245,1,0,0,0,247, - 248,1,0,0,0,248,19,1,0,0,0,249,247,1,0,0,0,250,251,3,54,27,0,251,261,5, - 44,0,0,252,262,5,65,0,0,253,258,3,10,5,0,254,255,5,38,0,0,255,257,3,10, - 5,0,256,254,1,0,0,0,257,260,1,0,0,0,258,256,1,0,0,0,258,259,1,0,0,0,259, - 262,1,0,0,0,260,258,1,0,0,0,261,252,1,0,0,0,261,253,1,0,0,0,261,262,1,0, - 0,0,262,263,1,0,0,0,263,264,5,54,0,0,264,21,1,0,0,0,265,266,3,54,27,0,266, - 23,1,0,0,0,267,268,5,16,0,0,268,269,3,26,13,0,269,25,1,0,0,0,270,275,3, - 28,14,0,271,272,5,38,0,0,272,274,3,28,14,0,273,271,1,0,0,0,274,277,1,0, - 0,0,275,273,1,0,0,0,275,276,1,0,0,0,276,27,1,0,0,0,277,275,1,0,0,0,278, - 284,3,10,5,0,279,280,3,48,24,0,280,281,5,36,0,0,281,282,3,10,5,0,282,284, - 1,0,0,0,283,278,1,0,0,0,283,279,1,0,0,0,284,29,1,0,0,0,285,286,5,6,0,0, - 286,291,3,32,16,0,287,288,5,38,0,0,288,290,3,32,16,0,289,287,1,0,0,0,290, - 293,1,0,0,0,291,289,1,0,0,0,291,292,1,0,0,0,292,295,1,0,0,0,293,291,1,0, - 0,0,294,296,3,34,17,0,295,294,1,0,0,0,295,296,1,0,0,0,296,31,1,0,0,0,297, - 298,5,25,0,0,298,33,1,0,0,0,299,302,3,36,18,0,300,302,3,38,19,0,301,299, - 1,0,0,0,301,300,1,0,0,0,302,35,1,0,0,0,303,304,5,75,0,0,304,309,3,32,16, - 0,305,306,5,38,0,0,306,308,3,32,16,0,307,305,1,0,0,0,308,311,1,0,0,0,309, - 307,1,0,0,0,309,310,1,0,0,0,310,37,1,0,0,0,311,309,1,0,0,0,312,313,5,68, - 0,0,313,314,3,36,18,0,314,315,5,69,0,0,315,39,1,0,0,0,316,317,5,13,0,0, - 317,322,3,32,16,0,318,319,5,38,0,0,319,321,3,32,16,0,320,318,1,0,0,0,321, - 324,1,0,0,0,322,320,1,0,0,0,322,323,1,0,0,0,323,326,1,0,0,0,324,322,1,0, - 0,0,325,327,3,26,13,0,326,325,1,0,0,0,326,327,1,0,0,0,327,330,1,0,0,0,328, - 329,5,33,0,0,329,331,3,26,13,0,330,328,1,0,0,0,330,331,1,0,0,0,331,41,1, - 0,0,0,332,333,5,4,0,0,333,334,3,26,13,0,334,43,1,0,0,0,335,337,5,19,0,0, - 336,338,3,26,13,0,337,336,1,0,0,0,337,338,1,0,0,0,338,341,1,0,0,0,339,340, - 5,33,0,0,340,342,3,26,13,0,341,339,1,0,0,0,341,342,1,0,0,0,342,45,1,0,0, - 0,343,344,5,8,0,0,344,347,3,26,13,0,345,346,5,33,0,0,346,348,3,26,13,0, - 347,345,1,0,0,0,347,348,1,0,0,0,348,47,1,0,0,0,349,354,3,54,27,0,350,351, - 5,40,0,0,351,353,3,54,27,0,352,350,1,0,0,0,353,356,1,0,0,0,354,352,1,0, - 0,0,354,355,1,0,0,0,355,49,1,0,0,0,356,354,1,0,0,0,357,362,3,56,28,0,358, - 359,5,40,0,0,359,361,3,56,28,0,360,358,1,0,0,0,361,364,1,0,0,0,362,360, - 1,0,0,0,362,363,1,0,0,0,363,51,1,0,0,0,364,362,1,0,0,0,365,370,3,50,25, - 0,366,367,5,38,0,0,367,369,3,50,25,0,368,366,1,0,0,0,369,372,1,0,0,0,370, - 368,1,0,0,0,370,371,1,0,0,0,371,53,1,0,0,0,372,370,1,0,0,0,373,374,7,2, - 0,0,374,55,1,0,0,0,375,376,5,79,0,0,376,57,1,0,0,0,377,420,5,49,0,0,378, - 379,3,90,45,0,379,380,5,70,0,0,380,420,1,0,0,0,381,420,3,88,44,0,382,420, - 3,90,45,0,383,420,3,84,42,0,384,420,5,52,0,0,385,420,3,92,46,0,386,387, - 5,68,0,0,387,392,3,86,43,0,388,389,5,38,0,0,389,391,3,86,43,0,390,388,1, - 0,0,0,391,394,1,0,0,0,392,390,1,0,0,0,392,393,1,0,0,0,393,395,1,0,0,0,394, - 392,1,0,0,0,395,396,5,69,0,0,396,420,1,0,0,0,397,398,5,68,0,0,398,403,3, - 84,42,0,399,400,5,38,0,0,400,402,3,84,42,0,401,399,1,0,0,0,402,405,1,0, - 0,0,403,401,1,0,0,0,403,404,1,0,0,0,404,406,1,0,0,0,405,403,1,0,0,0,406, - 407,5,69,0,0,407,420,1,0,0,0,408,409,5,68,0,0,409,414,3,92,46,0,410,411, - 5,38,0,0,411,413,3,92,46,0,412,410,1,0,0,0,413,416,1,0,0,0,414,412,1,0, - 0,0,414,415,1,0,0,0,415,417,1,0,0,0,416,414,1,0,0,0,417,418,5,69,0,0,418, - 420,1,0,0,0,419,377,1,0,0,0,419,378,1,0,0,0,419,381,1,0,0,0,419,382,1,0, - 0,0,419,383,1,0,0,0,419,384,1,0,0,0,419,385,1,0,0,0,419,386,1,0,0,0,419, - 397,1,0,0,0,419,408,1,0,0,0,420,59,1,0,0,0,421,422,5,10,0,0,422,423,5,31, - 0,0,423,61,1,0,0,0,424,425,5,18,0,0,425,430,3,64,32,0,426,427,5,38,0,0, - 427,429,3,64,32,0,428,426,1,0,0,0,429,432,1,0,0,0,430,428,1,0,0,0,430,431, - 1,0,0,0,431,63,1,0,0,0,432,430,1,0,0,0,433,435,3,10,5,0,434,436,7,3,0,0, - 435,434,1,0,0,0,435,436,1,0,0,0,436,439,1,0,0,0,437,438,5,50,0,0,438,440, - 7,4,0,0,439,437,1,0,0,0,439,440,1,0,0,0,440,65,1,0,0,0,441,442,5,9,0,0, - 442,443,3,52,26,0,443,67,1,0,0,0,444,445,5,2,0,0,445,446,3,52,26,0,446, - 69,1,0,0,0,447,448,5,15,0,0,448,453,3,72,36,0,449,450,5,38,0,0,450,452, - 3,72,36,0,451,449,1,0,0,0,452,455,1,0,0,0,453,451,1,0,0,0,453,454,1,0,0, - 0,454,71,1,0,0,0,455,453,1,0,0,0,456,457,3,50,25,0,457,458,5,83,0,0,458, - 459,3,50,25,0,459,73,1,0,0,0,460,461,5,1,0,0,461,462,3,18,9,0,462,464,3, - 92,46,0,463,465,3,80,40,0,464,463,1,0,0,0,464,465,1,0,0,0,465,75,1,0,0, - 0,466,467,5,7,0,0,467,468,3,18,9,0,468,469,3,92,46,0,469,77,1,0,0,0,470, - 471,5,14,0,0,471,472,3,48,24,0,472,79,1,0,0,0,473,478,3,82,41,0,474,475, - 5,38,0,0,475,477,3,82,41,0,476,474,1,0,0,0,477,480,1,0,0,0,478,476,1,0, - 0,0,478,479,1,0,0,0,479,81,1,0,0,0,480,478,1,0,0,0,481,482,3,54,27,0,482, - 483,5,36,0,0,483,484,3,58,29,0,484,83,1,0,0,0,485,486,7,5,0,0,486,85,1, - 0,0,0,487,490,3,88,44,0,488,490,3,90,45,0,489,487,1,0,0,0,489,488,1,0,0, - 0,490,87,1,0,0,0,491,493,7,0,0,0,492,491,1,0,0,0,492,493,1,0,0,0,493,494, - 1,0,0,0,494,495,5,32,0,0,495,89,1,0,0,0,496,498,7,0,0,0,497,496,1,0,0,0, - 497,498,1,0,0,0,498,499,1,0,0,0,499,500,5,31,0,0,500,91,1,0,0,0,501,502, - 5,30,0,0,502,93,1,0,0,0,503,504,7,6,0,0,504,95,1,0,0,0,505,506,5,5,0,0, - 506,507,3,98,49,0,507,97,1,0,0,0,508,509,5,68,0,0,509,510,3,2,1,0,510,511, - 5,69,0,0,511,99,1,0,0,0,512,513,5,17,0,0,513,514,5,105,0,0,514,101,1,0, - 0,0,515,516,5,12,0,0,516,517,5,109,0,0,517,103,1,0,0,0,518,519,5,3,0,0, - 519,522,5,89,0,0,520,521,5,87,0,0,521,523,3,50,25,0,522,520,1,0,0,0,522, - 523,1,0,0,0,523,533,1,0,0,0,524,525,5,88,0,0,525,530,3,106,53,0,526,527, - 5,38,0,0,527,529,3,106,53,0,528,526,1,0,0,0,529,532,1,0,0,0,530,528,1,0, - 0,0,530,531,1,0,0,0,531,534,1,0,0,0,532,530,1,0,0,0,533,524,1,0,0,0,533, - 534,1,0,0,0,534,105,1,0,0,0,535,536,3,50,25,0,536,537,5,36,0,0,537,539, - 1,0,0,0,538,535,1,0,0,0,538,539,1,0,0,0,539,540,1,0,0,0,540,541,3,50,25, - 0,541,107,1,0,0,0,542,543,5,11,0,0,543,544,5,25,0,0,544,545,5,87,0,0,545, - 546,3,52,26,0,546,109,1,0,0,0,52,121,130,146,158,167,175,179,187,189,194, - 201,206,213,219,227,229,240,247,258,261,275,283,291,295,301,309,322,326, - 330,337,341,347,354,362,370,392,403,414,419,430,435,439,453,464,478,489, - 492,497,522,530,533,538]; + 7,53,2,54,7,54,2,55,7,55,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,5,1,122,8, + 1,10,1,12,1,125,9,1,1,2,1,2,1,2,1,2,1,2,1,2,3,2,133,8,2,1,3,1,3,1,3,1,3, + 1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,3,3,149,8,3,1,4,1,4,1,4,1,5,1,5, + 1,5,1,5,1,5,1,5,1,5,3,5,161,8,5,1,5,1,5,1,5,1,5,1,5,5,5,168,8,5,10,5,12, + 5,171,9,5,1,5,1,5,1,5,1,5,1,5,3,5,178,8,5,1,5,1,5,3,5,182,8,5,1,5,1,5,1, + 5,1,5,1,5,1,5,5,5,190,8,5,10,5,12,5,193,9,5,1,6,1,6,3,6,197,8,6,1,6,1,6, + 1,6,1,6,1,6,3,6,204,8,6,1,6,1,6,1,6,3,6,209,8,6,1,7,1,7,1,7,1,7,1,7,3,7, + 216,8,7,1,8,1,8,1,8,1,8,3,8,222,8,8,1,8,1,8,1,8,1,8,1,8,1,8,5,8,230,8,8, + 10,8,12,8,233,9,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,3,9,243,8,9,1,9,1,9,1, + 9,5,9,248,8,9,10,9,12,9,251,9,9,1,10,1,10,1,10,1,10,1,10,1,10,5,10,259, + 8,10,10,10,12,10,262,9,10,3,10,264,8,10,1,10,1,10,1,11,1,11,1,12,1,12,1, + 12,1,13,1,13,1,13,5,13,276,8,13,10,13,12,13,279,9,13,1,14,1,14,1,14,1,14, + 1,14,3,14,286,8,14,1,15,1,15,1,15,1,15,5,15,292,8,15,10,15,12,15,295,9, + 15,1,15,3,15,298,8,15,1,16,1,16,1,17,1,17,3,17,304,8,17,1,18,1,18,1,18, + 1,18,5,18,310,8,18,10,18,12,18,313,9,18,1,19,1,19,1,19,1,19,1,20,1,20,1, + 20,1,20,5,20,323,8,20,10,20,12,20,326,9,20,1,20,3,20,329,8,20,1,20,1,20, + 3,20,333,8,20,1,21,1,21,1,21,1,22,1,22,3,22,340,8,22,1,22,1,22,3,22,344, + 8,22,1,23,1,23,1,23,1,23,3,23,350,8,23,1,24,1,24,1,24,5,24,355,8,24,10, + 24,12,24,358,9,24,1,25,1,25,1,25,5,25,363,8,25,10,25,12,25,366,9,25,1,26, + 1,26,1,26,5,26,371,8,26,10,26,12,26,374,9,26,1,27,1,27,1,28,1,28,1,29,1, + 29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,393,8,29, + 10,29,12,29,396,9,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,404,8,29,10,29, + 12,29,407,9,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,415,8,29,10,29,12,29, + 418,9,29,1,29,1,29,3,29,422,8,29,1,30,1,30,3,30,426,8,30,1,31,1,31,1,31, + 1,32,1,32,1,32,1,32,5,32,435,8,32,10,32,12,32,438,9,32,1,33,1,33,3,33,442, + 8,33,1,33,1,33,3,33,446,8,33,1,34,1,34,1,34,1,35,1,35,1,35,1,36,1,36,1, + 36,1,36,5,36,458,8,36,10,36,12,36,461,9,36,1,37,1,37,1,37,1,37,1,38,1,38, + 1,38,1,38,3,38,471,8,38,1,39,1,39,1,39,1,39,1,40,1,40,1,40,1,41,1,41,1, + 41,5,41,483,8,41,10,41,12,41,486,9,41,1,42,1,42,1,42,1,42,1,43,1,43,1,44, + 1,44,3,44,496,8,44,1,45,3,45,499,8,45,1,45,1,45,1,46,3,46,504,8,46,1,46, + 1,46,1,47,1,47,1,48,1,48,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,51,1,51,1, + 51,1,52,1,52,1,52,1,53,1,53,1,53,1,53,3,53,529,8,53,1,53,1,53,1,53,1,53, + 5,53,535,8,53,10,53,12,53,538,9,53,3,53,540,8,53,1,54,1,54,1,54,3,54,545, + 8,54,1,54,1,54,1,55,1,55,1,55,1,55,1,55,1,55,0,4,2,10,16,18,56,0,2,4,6, + 8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54, + 56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102, + 104,106,108,110,0,7,1,0,63,64,1,0,65,67,1,0,71,72,2,0,35,35,39,39,1,0,42, + 43,2,0,41,41,55,55,2,0,56,56,58,62,580,0,112,1,0,0,0,2,115,1,0,0,0,4,132, + 1,0,0,0,6,148,1,0,0,0,8,150,1,0,0,0,10,181,1,0,0,0,12,208,1,0,0,0,14,215, + 1,0,0,0,16,221,1,0,0,0,18,242,1,0,0,0,20,252,1,0,0,0,22,267,1,0,0,0,24, + 269,1,0,0,0,26,272,1,0,0,0,28,285,1,0,0,0,30,287,1,0,0,0,32,299,1,0,0,0, + 34,303,1,0,0,0,36,305,1,0,0,0,38,314,1,0,0,0,40,318,1,0,0,0,42,334,1,0, + 0,0,44,337,1,0,0,0,46,345,1,0,0,0,48,351,1,0,0,0,50,359,1,0,0,0,52,367, + 1,0,0,0,54,375,1,0,0,0,56,377,1,0,0,0,58,421,1,0,0,0,60,425,1,0,0,0,62, + 427,1,0,0,0,64,430,1,0,0,0,66,439,1,0,0,0,68,447,1,0,0,0,70,450,1,0,0,0, + 72,453,1,0,0,0,74,462,1,0,0,0,76,466,1,0,0,0,78,472,1,0,0,0,80,476,1,0, + 0,0,82,479,1,0,0,0,84,487,1,0,0,0,86,491,1,0,0,0,88,495,1,0,0,0,90,498, + 1,0,0,0,92,503,1,0,0,0,94,507,1,0,0,0,96,509,1,0,0,0,98,511,1,0,0,0,100, + 514,1,0,0,0,102,518,1,0,0,0,104,521,1,0,0,0,106,524,1,0,0,0,108,544,1,0, + 0,0,110,548,1,0,0,0,112,113,3,2,1,0,113,114,5,0,0,1,114,1,1,0,0,0,115,116, + 6,1,-1,0,116,117,3,4,2,0,117,123,1,0,0,0,118,119,10,1,0,0,119,120,5,29, + 0,0,120,122,3,6,3,0,121,118,1,0,0,0,122,125,1,0,0,0,123,121,1,0,0,0,123, + 124,1,0,0,0,124,3,1,0,0,0,125,123,1,0,0,0,126,133,3,98,49,0,127,133,3,30, + 15,0,128,133,3,24,12,0,129,133,3,40,20,0,130,133,3,102,51,0,131,133,3,104, + 52,0,132,126,1,0,0,0,132,127,1,0,0,0,132,128,1,0,0,0,132,129,1,0,0,0,132, + 130,1,0,0,0,132,131,1,0,0,0,133,5,1,0,0,0,134,149,3,42,21,0,135,149,3,46, + 23,0,136,149,3,62,31,0,137,149,3,110,55,0,138,149,3,68,34,0,139,149,3,64, + 32,0,140,149,3,44,22,0,141,149,3,8,4,0,142,149,3,70,35,0,143,149,3,72,36, + 0,144,149,3,76,38,0,145,149,3,78,39,0,146,149,3,106,53,0,147,149,3,80,40, + 0,148,134,1,0,0,0,148,135,1,0,0,0,148,136,1,0,0,0,148,137,1,0,0,0,148,138, + 1,0,0,0,148,139,1,0,0,0,148,140,1,0,0,0,148,141,1,0,0,0,148,142,1,0,0,0, + 148,143,1,0,0,0,148,144,1,0,0,0,148,145,1,0,0,0,148,146,1,0,0,0,148,147, + 1,0,0,0,149,7,1,0,0,0,150,151,5,20,0,0,151,152,3,10,5,0,152,9,1,0,0,0,153, + 154,6,5,-1,0,154,155,5,48,0,0,155,182,3,10,5,7,156,182,3,14,7,0,157,182, + 3,12,6,0,158,160,3,14,7,0,159,161,5,48,0,0,160,159,1,0,0,0,160,161,1,0, + 0,0,161,162,1,0,0,0,162,163,5,45,0,0,163,164,5,44,0,0,164,169,3,14,7,0, + 165,166,5,38,0,0,166,168,3,14,7,0,167,165,1,0,0,0,168,171,1,0,0,0,169,167, + 1,0,0,0,169,170,1,0,0,0,170,172,1,0,0,0,171,169,1,0,0,0,172,173,5,54,0, + 0,173,182,1,0,0,0,174,175,3,14,7,0,175,177,5,46,0,0,176,178,5,48,0,0,177, + 176,1,0,0,0,177,178,1,0,0,0,178,179,1,0,0,0,179,180,5,49,0,0,180,182,1, + 0,0,0,181,153,1,0,0,0,181,156,1,0,0,0,181,157,1,0,0,0,181,158,1,0,0,0,181, + 174,1,0,0,0,182,191,1,0,0,0,183,184,10,4,0,0,184,185,5,34,0,0,185,190,3, + 10,5,5,186,187,10,3,0,0,187,188,5,51,0,0,188,190,3,10,5,4,189,183,1,0,0, + 0,189,186,1,0,0,0,190,193,1,0,0,0,191,189,1,0,0,0,191,192,1,0,0,0,192,11, + 1,0,0,0,193,191,1,0,0,0,194,196,3,14,7,0,195,197,5,48,0,0,196,195,1,0,0, + 0,196,197,1,0,0,0,197,198,1,0,0,0,198,199,5,47,0,0,199,200,3,94,47,0,200, + 209,1,0,0,0,201,203,3,14,7,0,202,204,5,48,0,0,203,202,1,0,0,0,203,204,1, + 0,0,0,204,205,1,0,0,0,205,206,5,53,0,0,206,207,3,94,47,0,207,209,1,0,0, + 0,208,194,1,0,0,0,208,201,1,0,0,0,209,13,1,0,0,0,210,216,3,16,8,0,211,212, + 3,16,8,0,212,213,3,96,48,0,213,214,3,16,8,0,214,216,1,0,0,0,215,210,1,0, + 0,0,215,211,1,0,0,0,216,15,1,0,0,0,217,218,6,8,-1,0,218,222,3,18,9,0,219, + 220,7,0,0,0,220,222,3,16,8,3,221,217,1,0,0,0,221,219,1,0,0,0,222,231,1, + 0,0,0,223,224,10,2,0,0,224,225,7,1,0,0,225,230,3,16,8,3,226,227,10,1,0, + 0,227,228,7,0,0,0,228,230,3,16,8,2,229,223,1,0,0,0,229,226,1,0,0,0,230, + 233,1,0,0,0,231,229,1,0,0,0,231,232,1,0,0,0,232,17,1,0,0,0,233,231,1,0, + 0,0,234,235,6,9,-1,0,235,243,3,58,29,0,236,243,3,48,24,0,237,243,3,20,10, + 0,238,239,5,44,0,0,239,240,3,10,5,0,240,241,5,54,0,0,241,243,1,0,0,0,242, + 234,1,0,0,0,242,236,1,0,0,0,242,237,1,0,0,0,242,238,1,0,0,0,243,249,1,0, + 0,0,244,245,10,1,0,0,245,246,5,37,0,0,246,248,3,22,11,0,247,244,1,0,0,0, + 248,251,1,0,0,0,249,247,1,0,0,0,249,250,1,0,0,0,250,19,1,0,0,0,251,249, + 1,0,0,0,252,253,3,54,27,0,253,263,5,44,0,0,254,264,5,65,0,0,255,260,3,10, + 5,0,256,257,5,38,0,0,257,259,3,10,5,0,258,256,1,0,0,0,259,262,1,0,0,0,260, + 258,1,0,0,0,260,261,1,0,0,0,261,264,1,0,0,0,262,260,1,0,0,0,263,254,1,0, + 0,0,263,255,1,0,0,0,263,264,1,0,0,0,264,265,1,0,0,0,265,266,5,54,0,0,266, + 21,1,0,0,0,267,268,3,54,27,0,268,23,1,0,0,0,269,270,5,16,0,0,270,271,3, + 26,13,0,271,25,1,0,0,0,272,277,3,28,14,0,273,274,5,38,0,0,274,276,3,28, + 14,0,275,273,1,0,0,0,276,279,1,0,0,0,277,275,1,0,0,0,277,278,1,0,0,0,278, + 27,1,0,0,0,279,277,1,0,0,0,280,286,3,10,5,0,281,282,3,48,24,0,282,283,5, + 36,0,0,283,284,3,10,5,0,284,286,1,0,0,0,285,280,1,0,0,0,285,281,1,0,0,0, + 286,29,1,0,0,0,287,288,5,6,0,0,288,293,3,32,16,0,289,290,5,38,0,0,290,292, + 3,32,16,0,291,289,1,0,0,0,292,295,1,0,0,0,293,291,1,0,0,0,293,294,1,0,0, + 0,294,297,1,0,0,0,295,293,1,0,0,0,296,298,3,34,17,0,297,296,1,0,0,0,297, + 298,1,0,0,0,298,31,1,0,0,0,299,300,5,25,0,0,300,33,1,0,0,0,301,304,3,36, + 18,0,302,304,3,38,19,0,303,301,1,0,0,0,303,302,1,0,0,0,304,35,1,0,0,0,305, + 306,5,76,0,0,306,311,3,32,16,0,307,308,5,38,0,0,308,310,3,32,16,0,309,307, + 1,0,0,0,310,313,1,0,0,0,311,309,1,0,0,0,311,312,1,0,0,0,312,37,1,0,0,0, + 313,311,1,0,0,0,314,315,5,69,0,0,315,316,3,36,18,0,316,317,5,70,0,0,317, + 39,1,0,0,0,318,319,5,13,0,0,319,324,3,32,16,0,320,321,5,38,0,0,321,323, + 3,32,16,0,322,320,1,0,0,0,323,326,1,0,0,0,324,322,1,0,0,0,324,325,1,0,0, + 0,325,328,1,0,0,0,326,324,1,0,0,0,327,329,3,26,13,0,328,327,1,0,0,0,328, + 329,1,0,0,0,329,332,1,0,0,0,330,331,5,33,0,0,331,333,3,26,13,0,332,330, + 1,0,0,0,332,333,1,0,0,0,333,41,1,0,0,0,334,335,5,4,0,0,335,336,3,26,13, + 0,336,43,1,0,0,0,337,339,5,19,0,0,338,340,3,26,13,0,339,338,1,0,0,0,339, + 340,1,0,0,0,340,343,1,0,0,0,341,342,5,33,0,0,342,344,3,26,13,0,343,341, + 1,0,0,0,343,344,1,0,0,0,344,45,1,0,0,0,345,346,5,8,0,0,346,349,3,26,13, + 0,347,348,5,33,0,0,348,350,3,26,13,0,349,347,1,0,0,0,349,350,1,0,0,0,350, + 47,1,0,0,0,351,356,3,54,27,0,352,353,5,40,0,0,353,355,3,54,27,0,354,352, + 1,0,0,0,355,358,1,0,0,0,356,354,1,0,0,0,356,357,1,0,0,0,357,49,1,0,0,0, + 358,356,1,0,0,0,359,364,3,56,28,0,360,361,5,40,0,0,361,363,3,56,28,0,362, + 360,1,0,0,0,363,366,1,0,0,0,364,362,1,0,0,0,364,365,1,0,0,0,365,51,1,0, + 0,0,366,364,1,0,0,0,367,372,3,50,25,0,368,369,5,38,0,0,369,371,3,50,25, + 0,370,368,1,0,0,0,371,374,1,0,0,0,372,370,1,0,0,0,372,373,1,0,0,0,373,53, + 1,0,0,0,374,372,1,0,0,0,375,376,7,2,0,0,376,55,1,0,0,0,377,378,5,80,0,0, + 378,57,1,0,0,0,379,422,5,49,0,0,380,381,3,92,46,0,381,382,5,71,0,0,382, + 422,1,0,0,0,383,422,3,90,45,0,384,422,3,92,46,0,385,422,3,86,43,0,386,422, + 3,60,30,0,387,422,3,94,47,0,388,389,5,69,0,0,389,394,3,88,44,0,390,391, + 5,38,0,0,391,393,3,88,44,0,392,390,1,0,0,0,393,396,1,0,0,0,394,392,1,0, + 0,0,394,395,1,0,0,0,395,397,1,0,0,0,396,394,1,0,0,0,397,398,5,70,0,0,398, + 422,1,0,0,0,399,400,5,69,0,0,400,405,3,86,43,0,401,402,5,38,0,0,402,404, + 3,86,43,0,403,401,1,0,0,0,404,407,1,0,0,0,405,403,1,0,0,0,405,406,1,0,0, + 0,406,408,1,0,0,0,407,405,1,0,0,0,408,409,5,70,0,0,409,422,1,0,0,0,410, + 411,5,69,0,0,411,416,3,94,47,0,412,413,5,38,0,0,413,415,3,94,47,0,414,412, + 1,0,0,0,415,418,1,0,0,0,416,414,1,0,0,0,416,417,1,0,0,0,417,419,1,0,0,0, + 418,416,1,0,0,0,419,420,5,70,0,0,420,422,1,0,0,0,421,379,1,0,0,0,421,380, + 1,0,0,0,421,383,1,0,0,0,421,384,1,0,0,0,421,385,1,0,0,0,421,386,1,0,0,0, + 421,387,1,0,0,0,421,388,1,0,0,0,421,399,1,0,0,0,421,410,1,0,0,0,422,59, + 1,0,0,0,423,426,5,52,0,0,424,426,5,68,0,0,425,423,1,0,0,0,425,424,1,0,0, + 0,426,61,1,0,0,0,427,428,5,10,0,0,428,429,5,31,0,0,429,63,1,0,0,0,430,431, + 5,18,0,0,431,436,3,66,33,0,432,433,5,38,0,0,433,435,3,66,33,0,434,432,1, + 0,0,0,435,438,1,0,0,0,436,434,1,0,0,0,436,437,1,0,0,0,437,65,1,0,0,0,438, + 436,1,0,0,0,439,441,3,10,5,0,440,442,7,3,0,0,441,440,1,0,0,0,441,442,1, + 0,0,0,442,445,1,0,0,0,443,444,5,50,0,0,444,446,7,4,0,0,445,443,1,0,0,0, + 445,446,1,0,0,0,446,67,1,0,0,0,447,448,5,9,0,0,448,449,3,52,26,0,449,69, + 1,0,0,0,450,451,5,2,0,0,451,452,3,52,26,0,452,71,1,0,0,0,453,454,5,15,0, + 0,454,459,3,74,37,0,455,456,5,38,0,0,456,458,3,74,37,0,457,455,1,0,0,0, + 458,461,1,0,0,0,459,457,1,0,0,0,459,460,1,0,0,0,460,73,1,0,0,0,461,459, + 1,0,0,0,462,463,3,50,25,0,463,464,5,84,0,0,464,465,3,50,25,0,465,75,1,0, + 0,0,466,467,5,1,0,0,467,468,3,18,9,0,468,470,3,94,47,0,469,471,3,82,41, + 0,470,469,1,0,0,0,470,471,1,0,0,0,471,77,1,0,0,0,472,473,5,7,0,0,473,474, + 3,18,9,0,474,475,3,94,47,0,475,79,1,0,0,0,476,477,5,14,0,0,477,478,3,48, + 24,0,478,81,1,0,0,0,479,484,3,84,42,0,480,481,5,38,0,0,481,483,3,84,42, + 0,482,480,1,0,0,0,483,486,1,0,0,0,484,482,1,0,0,0,484,485,1,0,0,0,485,83, + 1,0,0,0,486,484,1,0,0,0,487,488,3,54,27,0,488,489,5,36,0,0,489,490,3,58, + 29,0,490,85,1,0,0,0,491,492,7,5,0,0,492,87,1,0,0,0,493,496,3,90,45,0,494, + 496,3,92,46,0,495,493,1,0,0,0,495,494,1,0,0,0,496,89,1,0,0,0,497,499,7, + 0,0,0,498,497,1,0,0,0,498,499,1,0,0,0,499,500,1,0,0,0,500,501,5,32,0,0, + 501,91,1,0,0,0,502,504,7,0,0,0,503,502,1,0,0,0,503,504,1,0,0,0,504,505, + 1,0,0,0,505,506,5,31,0,0,506,93,1,0,0,0,507,508,5,30,0,0,508,95,1,0,0,0, + 509,510,7,6,0,0,510,97,1,0,0,0,511,512,5,5,0,0,512,513,3,100,50,0,513,99, + 1,0,0,0,514,515,5,69,0,0,515,516,3,2,1,0,516,517,5,70,0,0,517,101,1,0,0, + 0,518,519,5,17,0,0,519,520,5,106,0,0,520,103,1,0,0,0,521,522,5,12,0,0,522, + 523,5,110,0,0,523,105,1,0,0,0,524,525,5,3,0,0,525,528,5,90,0,0,526,527, + 5,88,0,0,527,529,3,50,25,0,528,526,1,0,0,0,528,529,1,0,0,0,529,539,1,0, + 0,0,530,531,5,89,0,0,531,536,3,108,54,0,532,533,5,38,0,0,533,535,3,108, + 54,0,534,532,1,0,0,0,535,538,1,0,0,0,536,534,1,0,0,0,536,537,1,0,0,0,537, + 540,1,0,0,0,538,536,1,0,0,0,539,530,1,0,0,0,539,540,1,0,0,0,540,107,1,0, + 0,0,541,542,3,50,25,0,542,543,5,36,0,0,543,545,1,0,0,0,544,541,1,0,0,0, + 544,545,1,0,0,0,545,546,1,0,0,0,546,547,3,50,25,0,547,109,1,0,0,0,548,549, + 5,11,0,0,549,550,5,25,0,0,550,551,5,88,0,0,551,552,3,52,26,0,552,111,1, + 0,0,0,53,123,132,148,160,169,177,181,189,191,196,203,208,215,221,229,231, + 242,249,260,263,277,285,293,297,303,311,324,328,332,339,343,349,356,364, + 372,394,405,416,421,425,436,441,445,459,470,484,495,498,503,528,536,539, + 544]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -4848,22 +4897,22 @@ export class NumericArrayLiteralContext extends ConstantContext { } } } -export class InputParamContext extends ConstantContext { +export class InputParamsContext extends ConstantContext { constructor(parser: esql_parser, ctx: ConstantContext) { super(parser, ctx.parentCtx, ctx.invokingState); super.copyFrom(ctx); } - public PARAM(): TerminalNode { - return this.getToken(esql_parser.PARAM, 0); + public params(): ParamsContext { + return this.getTypedRuleContext(ParamsContext, 0) as ParamsContext; } public enterRule(listener: esql_parserListener): void { - if(listener.enterInputParam) { - listener.enterInputParam(this); + if(listener.enterInputParams) { + listener.enterInputParams(this); } } public exitRule(listener: esql_parserListener): void { - if(listener.exitInputParam) { - listener.exitInputParam(this); + if(listener.exitInputParams) { + listener.exitInputParams(this); } } } @@ -4907,6 +4956,58 @@ export class BooleanLiteralContext extends ConstantContext { } +export class ParamsContext extends ParserRuleContext { + constructor(parser?: esql_parser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public get ruleIndex(): number { + return esql_parser.RULE_params; + } + public copyFrom(ctx: ParamsContext): void { + super.copyFrom(ctx); + } +} +export class InputNamedOrPositionalParamContext extends ParamsContext { + constructor(parser: esql_parser, ctx: ParamsContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public NAMED_OR_POSITIONAL_PARAM(): TerminalNode { + return this.getToken(esql_parser.NAMED_OR_POSITIONAL_PARAM, 0); + } + public enterRule(listener: esql_parserListener): void { + if(listener.enterInputNamedOrPositionalParam) { + listener.enterInputNamedOrPositionalParam(this); + } + } + public exitRule(listener: esql_parserListener): void { + if(listener.exitInputNamedOrPositionalParam) { + listener.exitInputNamedOrPositionalParam(this); + } + } +} +export class InputParamContext extends ParamsContext { + constructor(parser: esql_parser, ctx: ParamsContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public PARAM(): TerminalNode { + return this.getToken(esql_parser.PARAM, 0); + } + public enterRule(listener: esql_parserListener): void { + if(listener.enterInputParam) { + listener.enterInputParam(this); + } + } + public exitRule(listener: esql_parserListener): void { + if(listener.exitInputParam) { + listener.exitInputParam(this); + } + } +} + + export class LimitCommandContext extends ParserRuleContext { constructor(parser?: esql_parser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts b/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts index 3b98e746de9b3..eee7a421a1593 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts +++ b/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts @@ -51,11 +51,13 @@ import { QualifiedIntegerLiteralContext } from "./esql_parser"; import { DecimalLiteralContext } from "./esql_parser"; import { IntegerLiteralContext } from "./esql_parser"; import { BooleanLiteralContext } from "./esql_parser"; -import { InputParamContext } from "./esql_parser"; +import { InputParamsContext } from "./esql_parser"; import { StringLiteralContext } from "./esql_parser"; import { NumericArrayLiteralContext } from "./esql_parser"; import { BooleanArrayLiteralContext } from "./esql_parser"; import { StringArrayLiteralContext } from "./esql_parser"; +import { InputParamContext } from "./esql_parser"; +import { InputNamedOrPositionalParamContext } from "./esql_parser"; import { LimitCommandContext } from "./esql_parser"; import { SortCommandContext } from "./esql_parser"; import { OrderExpressionContext } from "./esql_parser"; @@ -607,17 +609,17 @@ export default class esql_parserListener extends ParseTreeListener { */ exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; /** - * Enter a parse tree produced by the `inputParam` + * Enter a parse tree produced by the `inputParams` * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ - enterInputParam?: (ctx: InputParamContext) => void; + enterInputParams?: (ctx: InputParamsContext) => void; /** - * Exit a parse tree produced by the `inputParam` + * Exit a parse tree produced by the `inputParams` * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ - exitInputParam?: (ctx: InputParamContext) => void; + exitInputParams?: (ctx: InputParamsContext) => void; /** * Enter a parse tree produced by the `stringLiteral` * labeled alternative in `esql_parser.constant`. @@ -666,6 +668,30 @@ export default class esql_parserListener extends ParseTreeListener { * @param ctx the parse tree */ exitStringArrayLiteral?: (ctx: StringArrayLiteralContext) => void; + /** + * Enter a parse tree produced by the `inputParam` + * labeled alternative in `esql_parser.params`. + * @param ctx the parse tree + */ + enterInputParam?: (ctx: InputParamContext) => void; + /** + * Exit a parse tree produced by the `inputParam` + * labeled alternative in `esql_parser.params`. + * @param ctx the parse tree + */ + exitInputParam?: (ctx: InputParamContext) => void; + /** + * Enter a parse tree produced by the `inputNamedOrPositionalParam` + * labeled alternative in `esql_parser.params`. + * @param ctx the parse tree + */ + enterInputNamedOrPositionalParam?: (ctx: InputNamedOrPositionalParamContext) => void; + /** + * Exit a parse tree produced by the `inputNamedOrPositionalParam` + * labeled alternative in `esql_parser.params`. + * @param ctx the parse tree + */ + exitInputNamedOrPositionalParam?: (ctx: InputNamedOrPositionalParamContext) => void; /** * Enter a parse tree produced by `esql_parser.limitCommand`. * @param ctx the parse tree diff --git a/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json b/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json index 68dbb6ce73041..0fc1b047700a2 100644 --- a/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json +++ b/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json @@ -290,7 +290,7 @@ { "query": "from index [METADATA _id, _source2]", "error": [ - "Metadata field [_source2] is not available. Available metadata fields are: [_version, _id, _index, _source]" + "Metadata field [_source2] is not available. Available metadata fields are: [_version, _id, _index, _source, _ignored]" ], "warning": [ "Square brackets '[]' need to be removed from FROM METADATA declaration" @@ -337,7 +337,7 @@ { "query": "from index METADATA _id, _source2", "error": [ - "Metadata field [_source2] is not available. Available metadata fields are: [_version, _id, _index, _source]" + "Metadata field [_source2] is not available. Available metadata fields are: [_version, _id, _index, _source, _ignored]" ], "warning": [] }, @@ -504,7 +504,7 @@ { "query": "row", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -612,7 +612,7 @@ { "query": "row var = 1 in (", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", "Error: [in] function expects exactly 2 arguments, got 1." ], "warning": [] @@ -2846,7 +2846,7 @@ { "query": "from a_index | dissect", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -2902,7 +2902,7 @@ { "query": "from a_index | dissect stringField \"%{firstWord}\" option = ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', 'null', '?', 'true', '+', '-', OPENING_BRACKET}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET}", "Invalid option for DISSECT: [option]" ], "warning": [] @@ -2941,7 +2941,7 @@ { "query": "from a_index | grok", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -3743,21 +3743,21 @@ { "query": "from a_index | where *+ numberField", "error": [ - "SyntaxError: extraneous input '*' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: extraneous input '*' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, { "query": "from a_index | where /+ numberField", "error": [ - "SyntaxError: extraneous input '/' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: extraneous input '/' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, { "query": "from a_index | where %+ numberField", "error": [ - "SyntaxError: extraneous input '%' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: extraneous input '%' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -4324,7 +4324,7 @@ { "query": "from a_index | eval ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -4367,7 +4367,7 @@ { "query": "from a_index | eval a=b, ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", "Unknown column [b]" ], "warning": [] @@ -4394,7 +4394,7 @@ { "query": "from a_index | eval a=round(numberField), ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -5220,21 +5220,21 @@ { "query": "from a_index | eval *+ numberField", "error": [ - "SyntaxError: extraneous input '*' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: extraneous input '*' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, { "query": "from a_index | eval /+ numberField", "error": [ - "SyntaxError: extraneous input '/' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: extraneous input '/' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, { "query": "from a_index | eval %+ numberField", "error": [ - "SyntaxError: extraneous input '%' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: extraneous input '%' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -6558,7 +6558,7 @@ { "query": "from a_index | eval not", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", "Error: [not] function expects exactly one argument, got 0." ], "warning": [] @@ -6566,7 +6566,7 @@ { "query": "from a_index | eval in", "error": [ - "SyntaxError: mismatched input 'in' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input 'in' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -7787,7 +7787,7 @@ { "query": "from a_index | stats by ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -7801,14 +7801,14 @@ { "query": "from a_index | stats numberField=", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, { "query": "from a_index | stats numberField=5 by ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -8422,7 +8422,7 @@ { "query": "from a_index | sort ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, @@ -8441,7 +8441,7 @@ { "query": "from a_index | sort numberField, ", "error": [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}" ], "warning": [] }, diff --git a/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts b/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts index 35a5ab9742561..939cd5507ae27 100644 --- a/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts +++ b/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts @@ -375,7 +375,7 @@ describe('validation logic', () => { describe('row', () => { testErrorsAndWarnings('row', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('row missing_column', ['Unknown column [missing_column]']); testErrorsAndWarnings('row fn()', ['Unknown function [fn]']); @@ -404,7 +404,7 @@ describe('validation logic', () => { "SyntaxError: mismatched input '' expecting '('", ]); testErrorsAndWarnings('row var = 1 in (', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", 'Error: [in] function expects exactly 2 arguments, got 1.', ]); testErrorsAndWarnings('row var = 1 not in ', [ @@ -782,7 +782,7 @@ describe('validation logic', () => { describe('dissect', () => { testErrorsAndWarnings('from a_index | dissect', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | dissect stringField', [ "SyntaxError: missing QUOTED_STRING at ''", @@ -807,7 +807,7 @@ describe('validation logic', () => { "SyntaxError: mismatched input '' expecting '='", ]); testErrorsAndWarnings('from a_index | dissect stringField "%{firstWord}" option = ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', 'null', '?', 'true', '+', '-', OPENING_BRACKET}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET}", 'Invalid option for DISSECT: [option]', ]); testErrorsAndWarnings('from a_index | dissect stringField "%{firstWord}" option = 1', [ @@ -836,7 +836,7 @@ describe('validation logic', () => { describe('grok', () => { testErrorsAndWarnings('from a_index | grok', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | grok stringField', [ "SyntaxError: missing QUOTED_STRING at ''", @@ -921,7 +921,7 @@ describe('validation logic', () => { } for (const wrongOp of ['*', '/', '%']) { testErrorsAndWarnings(`from a_index | where ${wrongOp}+ numberField`, [ - `SyntaxError: extraneous input '${wrongOp}' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}`, + `SyntaxError: extraneous input '${wrongOp}' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}`, ]); } @@ -994,7 +994,7 @@ describe('validation logic', () => { describe('eval', () => { testErrorsAndWarnings('from a_index | eval ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | eval stringField ', []); testErrorsAndWarnings('from a_index | eval b = stringField', []); @@ -1007,7 +1007,7 @@ describe('validation logic', () => { ]); testErrorsAndWarnings('from a_index | eval a=b', ['Unknown column [b]']); testErrorsAndWarnings('from a_index | eval a=b, ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", 'Unknown column [b]', ]); testErrorsAndWarnings('from a_index | eval a=round', ['Unknown column [round]']); @@ -1016,7 +1016,7 @@ describe('validation logic', () => { ]); testErrorsAndWarnings('from a_index | eval a=round(numberField) ', []); testErrorsAndWarnings('from a_index | eval a=round(numberField), ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | eval a=round(numberField) + round(numberField) ', []); testErrorsAndWarnings('from a_index | eval a=round(numberField) + round(stringField) ', [ @@ -1079,7 +1079,7 @@ describe('validation logic', () => { for (const wrongOp of ['*', '/', '%']) { testErrorsAndWarnings(`from a_index | eval ${wrongOp}+ numberField`, [ - `SyntaxError: extraneous input '${wrongOp}' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}`, + `SyntaxError: extraneous input '${wrongOp}' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}`, ]); } testErrorsAndWarnings( @@ -1283,11 +1283,11 @@ describe('validation logic', () => { [] ); testErrorsAndWarnings('from a_index | eval not', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", 'Error: [not] function expects exactly one argument, got 0.', ]); testErrorsAndWarnings('from a_index | eval in', [ - "SyntaxError: mismatched input 'in' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input 'in' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | eval stringField in stringField', [ @@ -1376,16 +1376,16 @@ describe('validation logic', () => { ]); testErrorsAndWarnings('from a_index | stats by stringField', []); testErrorsAndWarnings('from a_index | stats by ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | stats numberField ', [ 'Expected an aggregate function or group but got [numberField] of type [FieldAttribute]', ]); testErrorsAndWarnings('from a_index | stats numberField=', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | stats numberField=5 by ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | stats avg(numberField) by wrongField', [ 'Unknown column [wrongField]', @@ -1596,12 +1596,12 @@ describe('validation logic', () => { describe('sort', () => { testErrorsAndWarnings('from a_index | sort ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | sort "field" ', []); testErrorsAndWarnings('from a_index | sort wrongField ', ['Unknown column [wrongField]']); testErrorsAndWarnings('from a_index | sort numberField, ', [ - "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", + "SyntaxError: mismatched input '' expecting {QUOTED_STRING, INTEGER_LITERAL, DECIMAL_LITERAL, 'false', '(', 'not', 'null', '?', 'true', '+', '-', NAMED_OR_POSITIONAL_PARAM, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER}", ]); testErrorsAndWarnings('from a_index | sort numberField, stringField', []); for (const dir of ['desc', 'asc']) { From 6fc0663d2ab068ba0a7ebac26bffc5ad00c30f49 Mon Sep 17 00:00:00 2001 From: Jordan <51442161+JordanSh@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:46:16 +0300 Subject: [PATCH 006/127] [Cloud Security] Serverless PLI auth block using UI extension infra (#184665) --- .buildkite/ftr_configs.yml | 3 +- .github/CODEOWNERS | 3 +- .../features/src/product_features_keys.ts | 5 + .../src/security/product_feature_config.ts | 1 + .../upselling/service/types.ts | 1 + .../single_page_layout/index.tsx | 338 ++++++++++-------- .../fleet/public/types/ui_extensions.ts | 9 +- ...urity_posture_pli_auth_block_extension.tsx | 22 ++ ...urity_posture_pli_auth_block_extension.tsx | 30 ++ .../components/with_security_context/index.ts | 0 .../render_context_providers.tsx | 16 +- .../components/with_security_context/store.ts | 16 +- .../with_security_context.tsx | 0 .../security_solution/public/common/types.ts | 11 + ...oint_agent_tamper_protection_extension.tsx | 4 +- .../lazy_endpoint_generic_errors_list.tsx | 4 +- ...lazy_endpoint_package_custom_extension.tsx | 4 +- .../lazy_endpoint_policy_create_extension.tsx | 4 +- .../lazy_endpoint_policy_edit_extension.tsx | 4 +- ...azy_endpoint_policy_response_extension.tsx | 4 +- .../view/ingest_manager_integration/mocks.tsx | 4 +- .../view/ingest_manager_integration/types.ts | 18 - .../security_solution/public/plugin.tsx | 10 +- .../common/pli/pli_config.ts | 2 +- .../public/upselling/register_upsellings.tsx | 18 +- ...security_posture_integration_pli_block.tsx | 64 ++++ .../sections/cloud_security_posture/index.ts | 16 + .../add_cis_integration_form_page.ts | 5 + .../test_serverless/functional/config.base.ts | 4 +- ...=> config.cloud_security_posture.basic.ts} | 2 + ...onfig.cloud_security_posture.essentials.ts | 26 ++ .../csp_integrations_form.essentials.ts | 35 ++ .../csp_integrations_form.ts | 35 ++ .../ftr/cloud_security_posture/index.ts | 3 + 34 files changed, 503 insertions(+), 218 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/cloud_security_posture/cloud_security_posture_pli_auth_block_extension.tsx create mode 100644 x-pack/plugins/security_solution/public/cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension.tsx rename x-pack/plugins/security_solution/public/{management/pages/policy/view/ingest_manager_integration => common}/components/with_security_context/index.ts (100%) rename x-pack/plugins/security_solution/public/{management/pages/policy/view/ingest_manager_integration => common}/components/with_security_context/render_context_providers.tsx (68%) rename x-pack/plugins/security_solution/public/{management/pages/policy/view/ingest_manager_integration => common}/components/with_security_context/store.ts (76%) rename x-pack/plugins/security_solution/public/{management/pages/policy/view/ingest_manager_integration => common}/components/with_security_context/with_security_context.tsx (100%) delete mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/types.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/upselling/sections/cloud_security_posture/cloud_security_posture_integration_pli_block.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/upselling/sections/cloud_security_posture/index.ts rename x-pack/test_serverless/functional/test_suites/security/{config.cloud_security_posture.ts => config.cloud_security_posture.basic.ts} (81%) create mode 100644 x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts create mode 100644 x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.essentials.ts create mode 100644 x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 433ab8b78b7a9..4a8b93d8d95dc 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -442,7 +442,8 @@ enabled: - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group6.ts - x-pack/test_serverless/functional/test_suites/security/config.ts - x-pack/test_serverless/functional/test_suites/security/config.examples.ts - - x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.ts + - x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.basic.ts + - x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts - x-pack/test_serverless/functional/test_suites/security/config.saved_objects_management.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group1.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group2.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6c544559319f9..dad6ef851a117 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1651,7 +1651,8 @@ x-pack/test/security_solution_api_integration/test_suites/genai @elastic/securit /x-pack/test/cloud_security_posture_functional/ @elastic/kibana-cloud-security-posture /x-pack/test/cloud_security_posture_api/ @elastic/kibana-cloud-security-posture /x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/ @elastic/kibana-cloud-security-posture -/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.ts @elastic/kibana-cloud-security-posture +/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.basic.ts @elastic/kibana-cloud-security-posture +/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts @elastic/kibana-cloud-security-posture /x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/ @elastic/kibana-cloud-security-posture /x-pack/plugins/fleet/public/components/cloud_security_posture @elastic/fleet @elastic/kibana-cloud-security-posture /x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/components/cloud_security_posture @elastic/fleet @elastic/kibana-cloud-security-posture diff --git a/x-pack/packages/security-solution/features/src/product_features_keys.ts b/x-pack/packages/security-solution/features/src/product_features_keys.ts index 5f6cd5f93b54b..be60a0edfdb3d 100644 --- a/x-pack/packages/security-solution/features/src/product_features_keys.ts +++ b/x-pack/packages/security-solution/features/src/product_features_keys.ts @@ -67,6 +67,11 @@ export enum ProductFeatureSecurityKey { * enables all rule actions */ externalRuleActions = 'external_rule_actions', + + /** + * enables Cloud Security Posture - CSPM, KSPM, CNVM + */ + cloudSecurityPosture = 'cloud_security_posture', } export enum ProductFeatureCasesKey { diff --git a/x-pack/packages/security-solution/features/src/security/product_feature_config.ts b/x-pack/packages/security-solution/features/src/security/product_feature_config.ts index 7fc2413e85e89..46ca114943795 100644 --- a/x-pack/packages/security-solution/features/src/security/product_feature_config.ts +++ b/x-pack/packages/security-solution/features/src/security/product_feature_config.ts @@ -121,4 +121,5 @@ export const securityDefaultProductFeaturesConfig: DefaultSecurityProductFeature [ProductFeatureSecurityKey.endpointProtectionUpdates]: {}, [ProductFeatureSecurityKey.endpointAgentTamperProtection]: {}, [ProductFeatureSecurityKey.externalRuleActions]: {}, + [ProductFeatureSecurityKey.cloudSecurityPosture]: {}, }; diff --git a/x-pack/packages/security-solution/upselling/service/types.ts b/x-pack/packages/security-solution/upselling/service/types.ts index 0b0d5b6e930f5..fdbd840429fec 100644 --- a/x-pack/packages/security-solution/upselling/service/types.ts +++ b/x-pack/packages/security-solution/upselling/service/types.ts @@ -17,6 +17,7 @@ export type UpsellingSectionId = | 'osquery_automated_response_actions' | 'endpoint_protection_updates' | 'endpoint_agent_tamper_protection' + | 'cloud_security_posture_integration_installation' | 'ruleDetailsEndpointExceptions'; export type UpsellingMessageId = 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 f264615222562..761153401ed06 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 @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState, Suspense } from 'react'; import { useRouteMatch } from 'react-router-dom'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; @@ -321,6 +321,20 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ 'package-policy-replace-define-step' ); + // PLI auth blocks are registered to UI Extension context and are used to display upselling components. + // Upselling components are rendered conditionally based on their availability from the PLI upselling service. + const pliAuthBlockView = useUIExtension(packageInfo?.name ?? '', 'pli-auth-block'); + + // If an auth block view is registered to the UI Extension context, we expect the registered component to return a React component when the PLI is not sufficient, + // or simply a wrapper returning the children if the PLI is sufficient. + const PliAuthBlockWrapper: React.FC = useMemo( + () => + pliAuthBlockView?.Component && !isPackageInfoLoading + ? pliAuthBlockView.Component + : ({ children }) => <>{children}, // when no UI Extension is registered, render children + [isPackageInfoLoading, pliAuthBlockView?.Component] + ); + if (replaceDefineStepView && extensionView) { throw new Error( "'package-policy-create' and 'package-policy-replace-define-step' cannot both be registered as UI extensions" @@ -455,172 +469,182 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ return ( - - {formState === 'CONFIRM' && agentPolicies.length > 0 && ( - setFormState('VALID')} - showUnprivilegedAgentsCallout={Boolean( - packageInfo && isRootPrivilegesRequired(packageInfo) && unprivilegedAgentsCount > 0 + }> + + + {formState === 'CONFIRM' && agentPolicies.length > 0 && ( + setFormState('VALID')} + showUnprivilegedAgentsCallout={Boolean( + packageInfo && + isRootPrivilegesRequired(packageInfo) && + unprivilegedAgentsCount > 0 + )} + unprivilegedAgentsCount={unprivilegedAgentsCount} + dataStreams={rootPrivilegedDataStreams} + /> )} - unprivilegedAgentsCount={unprivilegedAgentsCount} - dataStreams={rootPrivilegedDataStreams} - /> - )} - {formState === 'SUBMITTED_NO_AGENTS' && - agentPolicies.length > 0 && - packageInfo && - savedPackagePolicy && ( - navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} - /> - )} - {formState === 'SUBMITTED_AZURE_ARM_TEMPLATE' && - agentPolicies.length > 0 && - savedPackagePolicy && ( - navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} - /> - )} - {formState === 'SUBMITTED_CLOUD_FORMATION' && - agentPolicies.length > 0 && - savedPackagePolicy && ( - navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} - /> - )} - {formState === 'SUBMITTED_GOOGLE_CLOUD_SHELL' && - agentPolicies.length > 0 && - savedPackagePolicy && ( - navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} - /> - )} - {packageInfo && ( - - )} - {packageInfo && isRootPrivilegesRequired(packageInfo) ? ( - <> - - - - ) : null} - {numTransformAssets > 0 ? ( - <> - - - - ) : null} - {showSecretsDisabledCallout && ( - <> - 0 && + packageInfo && + savedPackagePolicy && ( + navigateAddAgent(savedPackagePolicy)} + onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} /> - } - > - - - - ), - minimumSecretsVersion: {SECRETS_MINIMUM_FLEET_SERVER_VERSION}, - }} - /> - - - - - )} - - - - - - - {packageInfo && (formState === 'INVALID' || hasAgentPolicyError) ? ( - 0 && + savedPackagePolicy && ( + navigateAddAgent(savedPackagePolicy)} + onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} /> - ) : null} - - - - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - + )} + {formState === 'SUBMITTED_CLOUD_FORMATION' && + agentPolicies.length > 0 && + savedPackagePolicy && ( + navigateAddAgent(savedPackagePolicy)} + onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} + /> + )} + {formState === 'SUBMITTED_GOOGLE_CLOUD_SHELL' && + agentPolicies.length > 0 && + savedPackagePolicy && ( + navigateAddAgent(savedPackagePolicy)} + onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} + /> + )} + {packageInfo && ( + + )} + {packageInfo && isRootPrivilegesRequired(packageInfo) ? ( + <> + + + + ) : null} + {numTransformAssets > 0 ? ( + <> + + + + ) : null} + {showSecretsDisabledCallout && ( + <> + - - - {showDevtoolsRequest ? ( - - - - ) : null} + } + > + + + + ), + minimumSecretsVersion: ( + {SECRETS_MINIMUM_FLEET_SERVER_VERSION} + ), + }} + /> + + + + + )} + + + + + - onSubmit()} - isLoading={formState === 'LOADING'} - disabled={formState !== 'VALID' || hasAgentPolicyError || !validationResults} - iconType="save" - color="primary" - fill - data-test-subj="createPackagePolicySaveButton" - > + {packageInfo && (formState === 'INVALID' || hasAgentPolicyError) ? ( - + ) : null} + + + + + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} + + + + + {showDevtoolsRequest ? ( + + + + ) : null} + + onSubmit()} + isLoading={formState === 'LOADING'} + disabled={ + formState !== 'VALID' || hasAgentPolicyError || !validationResults + } + iconType="save" + color="primary" + fill + data-test-subj="createPackagePolicySaveButton" + > + + + + - - - - + + + + ); }; diff --git a/x-pack/plugins/fleet/public/types/ui_extensions.ts b/x-pack/plugins/fleet/public/types/ui_extensions.ts index a041762438b8d..b0445bf4e1697 100644 --- a/x-pack/plugins/fleet/public/types/ui_extensions.ts +++ b/x-pack/plugins/fleet/public/types/ui_extensions.ts @@ -119,6 +119,12 @@ export interface EndpointAgentTamperProtectionExtension { Component: LazyExoticComponent; } +export interface PliAuthBlockExtension { + package: string; + view: 'pli-auth-block'; + Component: LazyExoticComponent; +} + export interface PackageGenericErrorsListExtension { package: string; view: 'package-generic-errors-list'; @@ -226,4 +232,5 @@ export type UIExtensionPoint = | PackageGenericErrorsListExtension | AgentEnrollmentFlyoutFinalStepExtension | PackagePolicyCreateMultiStepExtension - | EndpointAgentTamperProtectionExtension; + | EndpointAgentTamperProtectionExtension + | PliAuthBlockExtension; diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/cloud_security_posture_pli_auth_block_extension.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/cloud_security_posture_pli_auth_block_extension.tsx new file mode 100644 index 0000000000000..9abc7bcfbdf82 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/cloud_security_posture_pli_auth_block_extension.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PropsWithChildren } from 'react'; +import React, { memo } from 'react'; +import { useUpsellingComponent } from '../common/hooks/use_upselling'; + +export const CloudSecurityPosturePliAuthBlockExtension = memo>( + ({ children }) => { + const Component = useUpsellingComponent('cloud_security_posture_integration_installation'); + if (!Component) { + return <>{children}; + } + return ; + } +); + +CloudSecurityPosturePliAuthBlockExtension.displayName = 'CloudSecurityPosturePliAuthBlockExtension'; diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension.tsx new file mode 100644 index 0000000000000..1e4ddebb236ff --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { lazy } from 'react'; +import type { FleetUiExtensionGetterOptions } from '../common/types'; + +export const getLazyCloudSecurityPosturePliAuthBlockExtension = ({ + coreStart, + depsStart, + services, +}: FleetUiExtensionGetterOptions) => + lazy(async () => { + const [{ withSecurityContext }, { CloudSecurityPosturePliAuthBlockExtension }] = + await Promise.all([ + import('../common/components/with_security_context/with_security_context'), + import('./cloud_security_posture_pli_auth_block_extension'), + ]); + return { + default: withSecurityContext({ + coreStart, + depsStart, + services, + WrappedComponent: CloudSecurityPosturePliAuthBlockExtension, + }), + }; + }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/index.ts b/x-pack/plugins/security_solution/public/common/components/with_security_context/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/index.ts rename to x-pack/plugins/security_solution/public/common/components/with_security_context/index.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx b/x-pack/plugins/security_solution/public/common/components/with_security_context/render_context_providers.tsx similarity index 68% rename from x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx rename to x-pack/plugins/security_solution/public/common/components/with_security_context/render_context_providers.tsx index 4ad30f3945ee6..0d493f1e305d5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/with_security_context/render_context_providers.tsx @@ -11,14 +11,14 @@ import { Provider as ReduxStoreProvider } from 'react-redux'; import type { Store } from 'redux'; import { NavigationProvider } from '@kbn/security-solution-navigation'; import type { UpsellingService } from '@kbn/security-solution-upselling/service'; -import { UpsellingProvider } from '../../../../../../../common/components/upselling_provider'; -import { UserPrivilegesProvider } from '../../../../../../../common/components/user_privileges/user_privileges_context'; -import type { SecuritySolutionQueryClient } from '../../../../../../../common/containers/query_client/query_client_provider'; -import { ReactQueryClientProvider } from '../../../../../../../common/containers/query_client/query_client_provider'; -import { SecuritySolutionStartDependenciesContext } from '../../../../../../../common/components/user_privileges/endpoint/security_solution_start_dependencies'; -import { CurrentLicense } from '../../../../../../../common/components/current_license'; -import type { StartPlugins } from '../../../../../../../types'; -import { useKibana } from '../../../../../../../common/lib/kibana'; +import { UpsellingProvider } from '../upselling_provider'; +import { UserPrivilegesProvider } from '../user_privileges/user_privileges_context'; +import type { SecuritySolutionQueryClient } from '../../containers/query_client/query_client_provider'; +import { ReactQueryClientProvider } from '../../containers/query_client/query_client_provider'; +import { SecuritySolutionStartDependenciesContext } from '../user_privileges/endpoint/security_solution_start_dependencies'; +import { CurrentLicense } from '../current_license'; +import type { StartPlugins } from '../../../types'; +import { useKibana } from '../../lib/kibana'; export type RenderContextProvidersProps = PropsWithChildren<{ store: Store; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/store.ts b/x-pack/plugins/security_solution/public/common/components/with_security_context/store.ts similarity index 76% rename from x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/store.ts rename to x-pack/plugins/security_solution/public/common/components/with_security_context/store.ts index 512408b5e27c3..5a1179a4f5695 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/store.ts +++ b/x-pack/plugins/security_solution/public/common/components/with_security_context/store.ts @@ -8,14 +8,14 @@ import type { Dispatch, Middleware, PreloadedState, ReducersMapObject } from 'redux'; import { applyMiddleware, combineReducers, compose, createStore } from 'redux'; import type { CoreStart } from '@kbn/core/public'; -import { managementReducer } from '../../../../../../store/reducer'; -import { appReducer } from '../../../../../../../common/store/app'; -import { ExperimentalFeaturesService } from '../../../../../../../common/experimental_features_service'; -import { managementMiddlewareFactory } from '../../../../../../store/middleware'; -import type { StartPlugins } from '../../../../../../../types'; -import type { State } from '../../../../../../../common/store'; -import type { AppAction } from '../../../../../../../common/store/actions'; -import type { Immutable } from '../../../../../../../../common/endpoint/types'; +import { managementReducer } from '../../../management/store/reducer'; +import { appReducer } from '../../store/app'; +import { ExperimentalFeaturesService } from '../../experimental_features_service'; +import { managementMiddlewareFactory } from '../../../management/store/middleware'; +import type { StartPlugins } from '../../../types'; +import type { State } from '../../store'; +import type { AppAction } from '../../store/actions'; +import type { Immutable } from '../../../../common/endpoint/types'; type ComposeType = typeof compose; declare global { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/with_security_context.tsx b/x-pack/plugins/security_solution/public/common/components/with_security_context/with_security_context.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/with_security_context.tsx rename to x-pack/plugins/security_solution/public/common/components/with_security_context/with_security_context.tsx diff --git a/x-pack/plugins/security_solution/public/common/types.ts b/x-pack/plugins/security_solution/public/common/types.ts index 02cc712b6ec90..bf92b43245252 100644 --- a/x-pack/plugins/security_solution/public/common/types.ts +++ b/x-pack/plugins/security_solution/public/common/types.ts @@ -8,6 +8,9 @@ import type { ResponseErrorAttributes } from '@kbn/core/server'; import type { DataViewBase } from '@kbn/es-query'; import type { FieldSpec } from '@kbn/data-views-plugin/common'; +import type { CoreStart } from '@kbn/core-lifecycle-browser'; +import type { UpsellingService } from '@kbn/security-solution-upselling/service'; +import type { StartPlugins } from '../types'; export interface ServerApiError { statusCode: number; @@ -32,3 +35,11 @@ export interface SecuritySolutionDataViewBase extends DataViewBase { export type AlertWorkflowStatus = 'open' | 'closed' | 'acknowledged'; export type Refetch = () => void; + +export interface FleetUiExtensionGetterOptions { + coreStart: CoreStart; + depsStart: Pick; + services: { + upsellingService: UpsellingService; + }; +} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension.tsx index 144ecbd4ab157..93e6536977ba0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension.tsx @@ -6,7 +6,7 @@ */ import { lazy } from 'react'; -import type { FleetUiExtensionGetterOptions } from './types'; +import type { FleetUiExtensionGetterOptions } from '../../../../../common/types'; export const getLazyEndpointAgentTamperProtectionExtension = ({ coreStart, @@ -16,7 +16,7 @@ export const getLazyEndpointAgentTamperProtectionExtension = ({ lazy(async () => { const [{ withSecurityContext }, { EndpointAgentTamperProtectionExtension }] = await Promise.all( [ - import('./components/with_security_context/with_security_context'), + import('../../../../../common/components/with_security_context/with_security_context'), import('./endpoint_agent_tamper_protection_extension'), ] ); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx index 07f13e6759891..873c3a6d9aca3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx @@ -10,7 +10,7 @@ import type { PackageGenericErrorsListComponent, PackageGenericErrorsListProps, } from '@kbn/fleet-plugin/public'; -import type { FleetUiExtensionGetterOptions } from './types'; +import type { FleetUiExtensionGetterOptions } from '../../../../../common/types'; export const getLazyEndpointGenericErrorsListExtension = ({ coreStart, @@ -19,7 +19,7 @@ export const getLazyEndpointGenericErrorsListExtension = ({ }: FleetUiExtensionGetterOptions) => { return lazy(async () => { const [{ withSecurityContext }, { EndpointGenericErrorsList }] = await Promise.all([ - import('./components/with_security_context/with_security_context'), + import('../../../../../common/components/with_security_context/with_security_context'), import('./endpoint_generic_errors_list'), ]); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_package_custom_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_package_custom_extension.tsx index e122ed4c4b26f..81c8ff33ec45a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_package_custom_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_package_custom_extension.tsx @@ -7,7 +7,7 @@ import { lazy } from 'react'; import type { PackageCustomExtensionComponent } from '@kbn/fleet-plugin/public'; -import type { FleetUiExtensionGetterOptions } from './types'; +import type { FleetUiExtensionGetterOptions } from '../../../../../common/types'; export const getLazyEndpointPackageCustomExtension = ({ coreStart, @@ -16,7 +16,7 @@ export const getLazyEndpointPackageCustomExtension = ({ }: FleetUiExtensionGetterOptions) => { return lazy(async () => { const [{ withSecurityContext }, { EndpointPackageCustomExtension }] = await Promise.all([ - import('./components/with_security_context/with_security_context'), + import('../../../../../common/components/with_security_context/with_security_context'), import('./endpoint_package_custom_extension'), ]); return { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_create_extension.tsx index 5955661c82864..51325e74f7570 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_create_extension.tsx @@ -7,7 +7,7 @@ import { lazy } from 'react'; import type { PackagePolicyCreateExtensionComponent } from '@kbn/fleet-plugin/public'; -import type { FleetUiExtensionGetterOptions } from './types'; +import type { FleetUiExtensionGetterOptions } from '../../../../../common/types'; export const getLazyEndpointPolicyCreateExtension = ({ coreStart, @@ -16,7 +16,7 @@ export const getLazyEndpointPolicyCreateExtension = ({ }: FleetUiExtensionGetterOptions) => { return lazy(async () => { const [{ withSecurityContext }, { EndpointPolicyCreateExtension }] = await Promise.all([ - import('./components/with_security_context/with_security_context'), + import('../../../../../common/components/with_security_context/with_security_context'), import('./endpoint_policy_create_extension'), ]); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_edit_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_edit_extension.tsx index 57b1c5b23c15e..80d36a7803733 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_edit_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_edit_extension.tsx @@ -10,7 +10,7 @@ import type { PackagePolicyEditExtensionComponent, PackagePolicyEditExtensionComponentProps, } from '@kbn/fleet-plugin/public'; -import type { FleetUiExtensionGetterOptions } from './types'; +import type { FleetUiExtensionGetterOptions } from '../../../../../common/types'; export const getLazyEndpointPolicyEditExtension = ({ coreStart, @@ -19,7 +19,7 @@ export const getLazyEndpointPolicyEditExtension = ({ }: FleetUiExtensionGetterOptions) => { return lazy(async () => { const [{ withSecurityContext }, { EndpointPolicyEditExtension }] = await Promise.all([ - import('./components/with_security_context/with_security_context'), + import('../../../../../common/components/with_security_context/with_security_context'), import('./endpoint_policy_edit_extension/endpoint_policy_edit_extension'), ]); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_response_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_response_extension.tsx index 88a49965dd89a..3a596bd4c6f92 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_response_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_response_extension.tsx @@ -10,7 +10,7 @@ import type { PackagePolicyResponseExtensionComponent, PackagePolicyResponseExtensionComponentProps, } from '@kbn/fleet-plugin/public'; -import type { FleetUiExtensionGetterOptions } from './types'; +import type { FleetUiExtensionGetterOptions } from '../../../../../common/types'; export const getLazyEndpointPolicyResponseExtension = ({ coreStart, @@ -19,7 +19,7 @@ export const getLazyEndpointPolicyResponseExtension = ({ }: FleetUiExtensionGetterOptions) => { return lazy(async () => { const [{ withSecurityContext }, { EndpointPolicyResponseExtension }] = await Promise.all([ - import('./components/with_security_context/with_security_context'), + import('../../../../../common/components/with_security_context/with_security_context'), import('./endpoint_policy_response_extension'), ]); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx index 7bad12cc0be9d..945a841c132fd 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx @@ -16,9 +16,9 @@ import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { deepFreeze } from '@kbn/std'; +import { createFleetContextReduxStore } from '../../../../../common/components/with_security_context/store'; import type { AppContextTestRender, UiRender } from '../../../../../common/mock/endpoint'; import { createAppRootMockRenderer } from '../../../../../common/mock/endpoint'; -import { createFleetContextReduxStore } from './components/with_security_context/store'; import type { ExperimentalFeatures } from '../../../../../../common/experimental_features'; import { allowedExperimentalValues } from '../../../../../../common/experimental_features'; import type { State } from '../../../../../common/store'; @@ -26,7 +26,7 @@ import { mockGlobalState } from '../../../../../common/mock'; import { managementReducer } from '../../../../store/reducer'; import { appReducer } from '../../../../../common/store/app'; import { ExperimentalFeaturesService } from '../../../../../common/experimental_features_service'; -import { RenderContextProviders } from './components/with_security_context/render_context_providers'; +import { RenderContextProviders } from '../../../../../common/components/with_security_context/render_context_providers'; import type { AppAction } from '../../../../../common/store/actions'; // Defined a private custom reducer that reacts to an action that enables us to update the diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/types.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/types.ts deleted file mode 100644 index 1e5b4260b2148..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { CoreStart } from '@kbn/core-lifecycle-browser'; -import type { UpsellingService } from '@kbn/security-solution-upselling/service'; -import type { StartPlugins } from '../../../../../types'; - -export interface FleetUiExtensionGetterOptions { - coreStart: CoreStart; - depsStart: Pick; - services: { - upsellingService: UpsellingService; - }; -} diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 7b0ff954371c0..991f591773aa7 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -20,8 +20,8 @@ import type { import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import type { TriggersAndActionsUIPublicPluginSetup } from '@kbn/triggers-actions-ui-plugin/public'; +import { getLazyCloudSecurityPosturePliAuthBlockExtension } from './cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension'; import { getLazyEndpointAgentTamperProtectionExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension'; -import type { FleetUiExtensionGetterOptions } from './management/pages/policy/view/ingest_manager_integration/types'; import type { PluginSetup, PluginStart, @@ -39,7 +39,7 @@ import { APP_ID, APP_UI_ID, APP_PATH, APP_ICON_SOLUTION } from '../common/consta import type { AppLinkItems } from './common/links'; import { updateAppLinks, type LinksPermissions } from './common/links'; import { registerDeepLinksUpdater } from './common/links/deep_links'; -import type { SecuritySolutionUiConfigType } from './common/types'; +import type { FleetUiExtensionGetterOptions, SecuritySolutionUiConfigType } from './common/types'; import { getLazyEndpointPolicyEditExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_edit_extension'; import { getLazyEndpointPolicyCreateExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_create_extension'; @@ -263,6 +263,12 @@ export class Plugin implements IPlugin { + // TODO: prefer to use getProductTypeByPLI(ProductFeatureKey.cloudSecurityPosture) after we change returned text to include "Protection" + const requiredPLI = 'Cloud Protection Essentials'; + + return ( + <> + + } + betaBadgeProps={{ + label: i18n.translate( + 'xpack.securitySolutionServerless.cloudSecurityPostureIntegrationPliBlock.badgeText', + { + defaultMessage: 'Cloud Protection Essentials', + } + ), + }} + title={ +

+ + {i18n.translate( + 'xpack.securitySolutionServerless.cloudSecurityPostureIntegrationPliBlock.cardTitle', + { + defaultMessage: 'Protection updates', + } + )} + +

+ } + > +
+ {i18n.translate( + 'xpack.securitySolutionServerless.cloudSecurityPostureIntegrationPliBlock.cardMessage', + { + defaultMessage: + 'To turn on CSPM, KSPM or CNVM, view your Cloud Posture Dashboards and generate findings of misconfiguration or vulnerabilities in your cloud environment, you must add {requiredPLI} under Manage --> Project features.', + values: { + requiredPLI, + }, + } + )} +
+
+ + ); +}); +CloudSecurityPostureIntegrationPliBlock.displayName = 'CloudSecurityPostureIntegrationPliBlock'; diff --git a/x-pack/plugins/security_solution_serverless/public/upselling/sections/cloud_security_posture/index.ts b/x-pack/plugins/security_solution_serverless/public/upselling/sections/cloud_security_posture/index.ts new file mode 100644 index 0000000000000..b5c5794e00185 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/upselling/sections/cloud_security_posture/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { lazy } from 'react'; + +export const CloudSecurityPostureIntegrationPliBlockLazy = lazy(() => + import('./cloud_security_posture_integration_pli_block').then( + ({ CloudSecurityPostureIntegrationPliBlock }) => ({ + default: CloudSecurityPostureIntegrationPliBlock, + }) + ) +); diff --git a/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts b/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts index 18df32bd71993..1a566a346ad4e 100644 --- a/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts +++ b/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts @@ -201,6 +201,10 @@ export function AddCisIntegrationFormPageProvider({ return await testSubjects.find('confirmModalTitleText'); }; + const checkIntegrationPliAuthBlockExists = async () => { + return await testSubjects.exists('cloud-security-posture-integration-pli-auth-block'); + }; + const fillInTextField = async (selector: string, text: string) => { const textField = await testSubjects.find(selector); await textField.type(text); @@ -282,5 +286,6 @@ export function AddCisIntegrationFormPageProvider({ selectValue, getValueInEditPage, isOptionChecked, + checkIntegrationPliAuthBlockExists, }; } diff --git a/x-pack/test_serverless/functional/config.base.ts b/x-pack/test_serverless/functional/config.base.ts index 07aa6c9af5318..916be8ecd5cf3 100644 --- a/x-pack/test_serverless/functional/config.base.ts +++ b/x-pack/test_serverless/functional/config.base.ts @@ -16,7 +16,6 @@ import type { CreateTestConfigOptions } from '../shared/types'; export function createTestConfig(options: CreateTestConfigOptions) { return async ({ readConfigFile }: FtrConfigProviderContext) => { const svlSharedConfig = await readConfigFile(require.resolve('../shared/config.base.ts')); - return { ...svlSharedConfig.getAll(), @@ -110,6 +109,9 @@ export function createTestConfig(options: CreateTestConfigOptions) { maintenanceWindows: { pathname: '/app/management/insightsAndAlerting/maintenanceWindows', }, + fleet: { + pathname: '/app/fleet', + }, }, // choose where screenshots should be saved screenshots: { diff --git a/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.ts b/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.basic.ts similarity index 81% rename from x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.ts rename to x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.basic.ts index 6a755c26e91d4..7063ec943dfba 100644 --- a/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.ts +++ b/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.basic.ts @@ -16,6 +16,8 @@ export default createTestConfig({ kbnServerArgs: [ `--xpack.fleet.packages.0.name=cloud_security_posture`, `--xpack.fleet.packages.0.version=${CLOUD_SECURITY_PLUGIN_VERSION}`, + // configs the environment to run on the basic product tier, which may include PLI block components or messages + `--xpack.securitySolutionServerless.productTypes=${JSON.stringify([])}`, ], // load tests in the index file testFiles: [require.resolve('./ftr/cloud_security_posture')], diff --git a/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts b/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts new file mode 100644 index 0000000000000..320b130e63e91 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../config.base'; + +export default createTestConfig({ + serverlessProject: 'security', + junit: { + reportName: 'Serverless Security Cloud Security Functional Tests', + }, + kbnServerArgs: [ + `--xpack.fleet.packages.0.name=cloud_security_posture`, + `--xpack.fleet.packages.0.version=1.5.2`, + `--xpack.securitySolutionServerless.productTypes=${JSON.stringify([ + { product_line: 'security', product_tier: 'essentials' }, + { product_line: 'endpoint', product_tier: 'essentials' }, + { product_line: 'cloud', product_tier: 'essentials' }, + ])}`, + ], + // we should only resolve files which are ending with `.essentials.ts` + testFiles: [require.resolve('./ftr/cloud_security_posture/csp_integrations_form.essentials.ts')], +}); diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.essentials.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.essentials.ts new file mode 100644 index 0000000000000..28f494598835a --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.essentials.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function (providerContext: FtrProviderContext) { + const { getPageObjects } = providerContext; + const pageObjects = getPageObjects(['cisAddIntegration', 'header', 'svlCommonPage']); + + describe('[Essentials PLI] Test Cloud Security Posture Integrations on Serverless', function () { + this.tags(['skipMKI']); + let cisIntegration: typeof pageObjects.cisAddIntegration; + + before(async () => { + await pageObjects.svlCommonPage.login(); + }); + + beforeEach(async () => { + cisIntegration = pageObjects.cisAddIntegration; + await cisIntegration.navigateToAddIntegrationCspmPage(); + }); + + it('[Essentials PLI] Integration installation form should be available with Essentials or Complete PLI', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const pliBlockExists = await cisIntegration.checkIntegrationPliAuthBlockExists(); + + expect(pliBlockExists).to.be(false); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.ts new file mode 100644 index 0000000000000..a136d707cdb84 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/csp_integrations_form.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function (providerContext: FtrProviderContext) { + const { getPageObjects } = providerContext; + const pageObjects = getPageObjects(['cisAddIntegration', 'header', 'svlCommonPage']); + + describe('Test Cloud Security Posture Integrations on Serverless', function () { + this.tags(['skipMKI']); + let cisIntegration: typeof pageObjects.cisAddIntegration; + + before(async () => { + await pageObjects.svlCommonPage.login(); + }); + + beforeEach(async () => { + cisIntegration = pageObjects.cisAddIntegration; + await cisIntegration.navigateToAddIntegrationCspmPage(); + }); + + it('Integration installation form should not be available without required PLI', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const pliBlockExists = await cisIntegration.checkIntegrationPliAuthBlockExists(); + + expect(pliBlockExists).to.be(true); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/index.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/index.ts index 4750199f7f566..c94ab36cd46df 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/index.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/index.ts @@ -10,6 +10,9 @@ import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('cloud_security_posture', function () { this.tags(['cloud_security_posture']); + + // do not resolve files which are ending with `.essentials.ts` loadTestFile(require.resolve('./compliance_dashboard')); + loadTestFile(require.resolve('./csp_integrations_form')); }); } From cd10c25c8177e6a028194ab7c7466f2144152391 Mon Sep 17 00:00:00 2001 From: jennypavlova Date: Mon, 17 Jun 2024 15:50:48 +0200 Subject: [PATCH 007/127] [Infra] Metadata: Fix the bug with nesting - ignore values nested > 3th level (#186213) ## Summary This is probably an edge case because it shouldn't happen if the metadata is in the defined structure. I saw this bug while testing with metricbeat (with oblt cluster it's not reproducible and some of the metrics were present in the metadata in this format: ``` info: { container: { ......... network: { ingress: { bytes: 1410228770498, // ignore }, egress: { bytes: 23527514469, // ignore }, }, .......... }, ``` In theory, we should not have this data there based on the metadata type and as it's a nested property it returned an error. https://github.com/elastic/kibana/assets/14139027/55b54ae4-63df-4574-bd93-ea33d3bc97f4 It happens because we have `container` > `network` > `ingress` > **bytes** and in metadata we don't support more than 3-level nesting - so the values can be like in this example: `container` > `image` > **name** - but the name should not be an object (it's a string in this case). This can happen also for other asset types in case of some unsupported metadata format. To make sure that we skip those values in such cases I added a check to skip them when we prepare the metadata for the table. ## Testing - Use metricbeat to monitor docker containers - Open the new container view and select the metadata tab - The table should be displayed without an error - There should not be an error even if the autorefresh is enabled in inventory --- .../infra/common/http_api/metadata_api.ts | 1 + .../asset_details/tabs/metadata/utils.test.ts | 46 +++++++++++++++++++ .../asset_details/tabs/metadata/utils.ts | 16 +++++-- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/common/http_api/metadata_api.ts b/x-pack/plugins/observability_solution/infra/common/http_api/metadata_api.ts index df7ade50b2140..f9db4df10ed1c 100644 --- a/x-pack/plugins/observability_solution/infra/common/http_api/metadata_api.ts +++ b/x-pack/plugins/observability_solution/infra/common/http_api/metadata_api.ts @@ -49,6 +49,7 @@ export const InfraMetadataContainerRT = rt.partial({ id: rt.string, runtime: rt.string, imageName: rt.string, + image: rt.partial({ name: rt.string }), }); export const InfraMetadataInstanceRT = rt.partial({ diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.test.ts index 5c78fca3f48db..04bfdf9945ff3 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.test.ts @@ -113,6 +113,52 @@ describe('#getAllFields', () => { expect(getAllFields(result)).toStrictEqual([{ name: 'host.os.name', value: 'Ubuntu' }]); }); + it('should map metadata with nested properties with container data removing >3th level nesting', async () => { + const result = { + id: 'host1', + name: 'host1', + features: [ + { + name: 'system.core', + source: 'metrics', + }, + ], + info: { + container: { + id: '33d16f043d5f8a7dcc2f9a2164920d0d7ca4c13a9f737bff3dbedb507d954b8e', + name: 'load-generator', + image: { + name: 'ghcr.io/open-telemetry/demo:latest-loadgenerator', // accept + }, + runtime: 'docker', + network: { + ingress: { + bytes: 1410228770498, // ignore + }, + egress: { + bytes: 23527514469, // ignore + }, + }, + }, + }, + } as InfraMetadata; + expect(getAllFields(result)).toStrictEqual([ + { + name: 'container.id', + value: '33d16f043d5f8a7dcc2f9a2164920d0d7ca4c13a9f737bff3dbedb507d954b8e', + }, + { name: 'container.name', value: 'load-generator' }, + { + name: 'container.image.name', + value: 'ghcr.io/open-telemetry/demo:latest-loadgenerator', + }, + { + name: 'container.runtime', + value: 'docker', + }, + ]); + }); + it('should map metadata with partial host, agent, could data', async () => { const result: InfraMetadata = { id: 'host1', diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.ts index 9e339659b5824..9e99816874565 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/utils.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { isPlainObject } from 'lodash'; import type { InfraMetadata } from '../../../../../common/http_api'; export interface Field { @@ -39,10 +40,17 @@ export const getAllFields = (metadata: InfraMetadata | null) => { value, }; } else { - return Object.entries(value ?? {}).map(([prop, subProp]) => ({ - name: `${category}.${property}.${prop}`, - value: subProp, - })); + return Object.entries(value ?? {}) + .map(([prop, subProp]) => { + if (!Array.isArray(subProp) && isPlainObject(subProp)) { + return { name: '', value: '' }; + } + return { + name: `${category}.${property}.${prop}`, + value: subProp, + }; + }) + .filter(({ name }) => name); } } return []; From a2c068a5f2622beb8a19a0161a47a43d83023c4b Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 17 Jun 2024 10:03:01 -0400 Subject: [PATCH 008/127] [Fleet] Filter space aware entities in Fleet UI/API (#184869) --- .buildkite/ftr_configs.yml | 2 +- .../fleet/common/types/models/agent.ts | 6 + .../common/types/models/enrollment_api_key.ts | 1 + .../collectors/agents_per_output.test.ts | 48 ++++- .../server/collectors/agents_per_output.ts | 2 +- x-pack/plugins/fleet/server/mocks/index.ts | 5 +- x-pack/plugins/fleet/server/plugin.ts | 12 ++ .../fleet/server/routes/agent/handlers.ts | 60 ++++-- .../server/routes/agent_policy/handlers.ts | 58 +++--- .../routes/enrollment_api_key/handler.ts | 36 +++- .../server/routes/setup/handlers.test.ts | 7 + .../routes/uninstall_token/handlers.test.ts | 40 +--- .../server/routes/uninstall_token/handlers.ts | 41 ++-- .../fleet/server/services/agent_policy.ts | 29 ++- .../services/agents/agent_service.test.ts | 86 ++++++-- .../server/services/agents/agent_service.ts | 30 ++- .../fleet/server/services/agents/crud.ts | 21 +- .../fleet/server/services/agents/helpers.ts | 1 + .../fleet/server/services/agents/status.ts | 19 +- .../services/agents/update_agent_tags.test.ts | 1 + .../api_keys/enrollment_api_key.test.ts | 51 ++++- .../services/api_keys/enrollment_api_key.ts | 57 ++++- .../fleet/server/services/app_context.ts | 14 +- .../server/services/preconfiguration.test.ts | 3 + .../security/uninstall_token_service/index.ts | 45 +++- .../fleet/server/types/request_context.ts | 4 + .../apis/space_awareness/agent_policies.ts | 106 ++++++++++ .../apis/space_awareness/agents.ts | 136 ++++++++++++ .../apis/space_awareness/api_helper.ts | 142 +++++++++++++ .../space_awareness/enrollment_api_keys.ts | 196 ++++++++++++++++++ .../apis/space_awareness/helpers.ts | 25 +++ .../apis/space_awareness/index.js | 15 ++ .../apis/space_awareness/space_helpers.ts | 24 +++ .../apis/space_awareness/uninstall_tokens.ts | 115 ++++++++++ .../config.space_awareness.ts | 38 ++++ 35 files changed, 1286 insertions(+), 190 deletions(-) create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/agent_policies.ts create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/agents.ts create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_api_keys.ts create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/helpers.ts create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/index.js create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/space_helpers.ts create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/uninstall_tokens.ts create mode 100644 x-pack/test/fleet_api_integration/config.space_awareness.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 4a8b93d8d95dc..aea151baae3a1 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -246,6 +246,7 @@ enabled: - x-pack/test/fleet_api_integration/config.epm.ts - x-pack/test/fleet_api_integration/config.fleet.ts - x-pack/test/fleet_api_integration/config.package_policy.ts + - x-pack/test/fleet_api_integration/config.space_awareness.ts - x-pack/test/fleet_functional/config.ts - x-pack/test/ftr_apis/security_and_spaces/config.ts - x-pack/test/functional_basic/apps/ml/permissions/config.ts @@ -573,4 +574,3 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint/configs/serverless.integrations.config.ts - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint/configs/serverless.integrations_feature_flag.config.ts - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint/configs/integrations_feature_flag.config.ts - diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index 89b533c47341f..2add5750f1855 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -108,6 +108,7 @@ interface AgentBase { components?: FleetServerAgentComponent[]; agent?: FleetServerAgentMetadata; unhealthy_reason?: UnhealthyReason[]; + namespaces?: string[]; } export enum UnhealthyReason { @@ -348,6 +349,11 @@ export interface FleetServerAgent { * Unhealthy reason: input, output, other */ unhealthy_reason?: UnhealthyReason[]; + + /** + * Namespaces + */ + namespaces?: string[]; } /** diff --git a/x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts b/x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts index 4398675831b45..1dc220b86059d 100644 --- a/x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts +++ b/x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts @@ -42,4 +42,5 @@ export interface FleetServerEnrollmentAPIKey { expire_at?: string; created_at?: string; updated_at?: string; + namespaces?: string[]; } diff --git a/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts b/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts index f68a700865708..181467a69cf1f 100644 --- a/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts +++ b/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts @@ -9,23 +9,57 @@ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/ import { getAgentsPerOutput } from './agents_per_output'; +jest.mock('../services/agents', () => { + return { + getAgentsByKuery: jest + .fn() + .mockImplementation(async (esClient, soClient, { kuery }: { kuery: string }) => { + if (kuery.includes('policy_id:policy1')) { + return { + total: 0, + }; + } else { + return { + total: 1, + }; + } + }), + }; +}); + jest.mock('../services', () => { return { agentPolicyService: { list: jest.fn().mockResolvedValue({ items: [ - { agents: 0, data_output_id: 'logstash1', monitoring_output_id: 'kafka1' }, - { agents: 1 }, - { agents: 1, data_output_id: 'logstash1' }, - { agents: 1, monitoring_output_id: 'kafka1' }, - { agents: 1, data_output_id: 'elasticsearch2', monitoring_output_id: 'elasticsearch2' }, - { agents: 1, data_output_id: 'elasticsearch3', monitoring_output_id: 'elasticsearch3' }, + { id: 'policy1', agents: 0, data_output_id: 'logstash1', monitoring_output_id: 'kafka1' }, + { id: 'policy2', agents: 1 }, + { id: 'policy3', agents: 1, data_output_id: 'logstash1' }, + { id: 'policy4', agents: 1, monitoring_output_id: 'kafka1' }, + { + id: 'policy5', + agents: 1, + data_output_id: 'elasticsearch2', + monitoring_output_id: 'elasticsearch2', + }, + { + id: 'policy5', + agents: 1, + data_output_id: 'elasticsearch3', + monitoring_output_id: 'elasticsearch3', + }, { + id: 'policy6', agents: 1, data_output_id: 'es-containerhost', monitoring_output_id: 'es-containerhost', }, - { agents: 1, data_output_id: 'remote-es', monitoring_output_id: 'remote-es' }, + { + id: 'policy7', + agents: 1, + data_output_id: 'remote-es', + monitoring_output_id: 'remote-es', + }, ], }), }, diff --git a/x-pack/plugins/fleet/server/collectors/agents_per_output.ts b/x-pack/plugins/fleet/server/collectors/agents_per_output.ts index 5090b1530bc02..a6d6254bc5276 100644 --- a/x-pack/plugins/fleet/server/collectors/agents_per_output.ts +++ b/x-pack/plugins/fleet/server/collectors/agents_per_output.ts @@ -46,9 +46,9 @@ export async function getAgentsPerOutput( const { items: agentPolicies } = await agentPolicyService.list(soClient, { esClient, - withAgentCount: true, page: 1, perPage: SO_SEARCH_LIMIT, + withAgentCount: true, }); const outputTypes: { [key: string]: AgentsPerOutputType } = {}; diff --git a/x-pack/plugins/fleet/server/mocks/index.ts b/x-pack/plugins/fleet/server/mocks/index.ts index 9e84626455b1b..781cc18e33425 100644 --- a/x-pack/plugins/fleet/server/mocks/index.ts +++ b/x-pack/plugins/fleet/server/mocks/index.ts @@ -121,6 +121,9 @@ export const createFleetRequestHandlerContextMock = (): jest.Mocked< asCurrentUser: createPackagePolicyServiceMock(), asInternalUser: createPackagePolicyServiceMock(), }, + uninstallTokenService: { + asCurrentUser: createUninstallTokenServiceMock(), + }, internalSoClient: savedObjectsClientMock.create(), spaceId: 'default', limitedToPackages: undefined, @@ -182,7 +185,6 @@ export const createPackagePolicyServiceMock = (): jest.Mocked => { return { get: jest.fn(), @@ -238,5 +240,6 @@ export function createUninstallTokenServiceMock(): UninstallTokenServiceInterfac encryptTokens: jest.fn(), checkTokenValidityForAllPolicies: jest.fn(), checkTokenValidityForPolicy: jest.fn(), + scoped: jest.fn().mockImplementation(() => createUninstallTokenServiceMock()), }; } diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 1c2ff2353a1a2..67240be2cc542 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -521,6 +521,18 @@ export class FleetPlugin asInternalUser: agentService.asInternalUser, }; }, + get uninstallTokenService() { + const uninstallTokenService = new UninstallTokenService( + appContextService.getEncryptedSavedObjectsStart()!.getClient({ + includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], + }), + appContextService.getInternalUserSOClientForSpaceId(soClient.getCurrentNamespace()) + ); + + return { + asCurrentUser: uninstallTokenService, + }; + }, get packagePolicyService() { const service = plugin.setupPackagePolicyService(); diff --git a/x-pack/plugins/fleet/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts index b292cc2f88c33..6f1ac12edb163 100644 --- a/x-pack/plugins/fleet/server/routes/agent/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/handlers.ts @@ -8,6 +8,7 @@ import { uniq } from 'lodash'; import { type RequestHandler, SavedObjectsErrorHelpers } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; +import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; import type { GetAgentsResponse, @@ -20,6 +21,7 @@ import type { GetAgentUploadsResponse, PostAgentReassignResponse, PostRetrieveAgentsByActionsResponse, + Agent, } from '../../../common/types'; import type { GetAgentsRequestSchema, @@ -37,22 +39,36 @@ import type { GetAgentUploadFileRequestSchema, DeleteAgentUploadFileRequestSchema, PostRetrieveAgentsByActionsRequestSchema, + FleetRequestHandler, } from '../../types'; -import { defaultFleetErrorHandler } from '../../errors'; +import { defaultFleetErrorHandler, FleetNotFoundError } from '../../errors'; import * as AgentService from '../../services/agents'; import { fetchAndAssignAgentMetrics } from '../../services/agents/agent_metrics'; +import { getAgentStatusForAgentPolicy } from '../../services/agents'; + +export function verifyNamespace(agent: Agent, currentNamespace?: string) { + const isInNamespace = + (currentNamespace && agent.namespaces?.includes(currentNamespace)) || + (!currentNamespace && + (!agent.namespaces || + agent.namespaces.length === 0 || + agent.namespaces?.includes(DEFAULT_NAMESPACE_STRING))); + if (!isInNamespace) { + throw new FleetNotFoundError(`${agent.id} not found in namespace`); + } +} -export const getAgentHandler: RequestHandler< +export const getAgentHandler: FleetRequestHandler< TypeOf, TypeOf > = async (context, request, response) => { - const coreContext = await context.core; - const esClient = coreContext.elasticsearch.client.asInternalUser; - const esClientCurrentUser = coreContext.elasticsearch.client.asCurrentUser; - const soClient = coreContext.savedObjects.client; - try { - let agent = await AgentService.getAgentById(esClient, soClient, request.params.agentId); + const [coreContext, fleetContext] = await Promise.all([context.core, context.fleet]); + const esClientCurrentUser = coreContext.elasticsearch.client.asCurrentUser; + + let agent = await fleetContext.agentClient.asCurrentUser.getAgent(request.params.agentId); + + verifyNamespace(agent, coreContext.savedObjects.client.getCurrentNamespace()); if (request.query.withMetrics) { agent = (await fetchAndAssignAgentMetrics(esClientCurrentUser, [agent]))[0]; @@ -77,10 +93,10 @@ export const getAgentHandler: RequestHandler< export const deleteAgentHandler: RequestHandler< TypeOf > = async (context, request, response) => { - const coreContext = await context.core; - const esClient = coreContext.elasticsearch.client.asInternalUser; - try { + const coreContext = await context.core; + const esClient = coreContext.elasticsearch.client.asInternalUser; + await AgentService.deleteAgent(esClient, request.params.agentId); const body = { @@ -162,17 +178,16 @@ export const bulkUpdateAgentTagsHandler: RequestHandler< } }; -export const getAgentsHandler: RequestHandler< +export const getAgentsHandler: FleetRequestHandler< undefined, TypeOf > = async (context, request, response) => { - const coreContext = await context.core; - const esClient = coreContext.elasticsearch.client.asInternalUser; + const [coreContext, fleetContext] = await Promise.all([context.core, context.fleet]); + const { agentClient } = fleetContext; const esClientCurrentUser = coreContext.elasticsearch.client.asCurrentUser; - const soClient = coreContext.savedObjects.client; try { - const agentRes = await AgentService.getAgentsByKuery(esClient, soClient, { + const agentRes = await agentClient.asCurrentUser.listAgents({ page: request.query.page, perPage: request.query.perPage, showInactive: request.query.showInactive, @@ -300,19 +315,20 @@ export const postBulkAgentReassignHandler: RequestHandler< } }; -export const getAgentStatusForAgentPolicyHandler: RequestHandler< +export const getAgentStatusForAgentPolicyHandler: FleetRequestHandler< undefined, TypeOf > = async (context, request, response) => { - const coreContext = await context.core; - const esClient = coreContext.elasticsearch.client.asInternalUser; - const soClient = coreContext.savedObjects.client; try { - const results = await AgentService.getAgentStatusForAgentPolicy( + const [coreContext, fleetContext] = await Promise.all([context.core, context.fleet]); + const esClient = coreContext.elasticsearch.client.asInternalUser; + const soClient = fleetContext.internalSoClient; + const results = await getAgentStatusForAgentPolicy( esClient, soClient, request.query.policyId, - request.query.kuery + request.query.kuery, + coreContext.savedObjects.client.getCurrentNamespace() ); const body: GetAgentStatusResponse = { results }; diff --git a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts index a5d6f7b83c854..d652dacf0dd9a 100644 --- a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts @@ -6,12 +6,7 @@ */ import type { TypeOf } from '@kbn/config-schema'; -import type { - RequestHandler, - ResponseHeaders, - ElasticsearchClient, - SavedObjectsClientContract, -} from '@kbn/core/server'; +import type { RequestHandler, ResponseHeaders } from '@kbn/core/server'; import pMap from 'p-map'; import { safeDump } from 'js-yaml'; @@ -19,7 +14,7 @@ import { HTTPAuthorizationHeader } from '../../../common/http_authorization_head import { fullAgentPolicyToYaml } from '../../../common/services'; import { appContextService, agentPolicyService } from '../../services'; -import { getAgentsByKuery, getLatestAvailableAgentVersion } from '../../services/agents'; +import { type AgentClient, getLatestAvailableAgentVersion } from '../../services/agents'; import { AGENTS_PREFIX, UNPRIVILEGED_AGENT_KUERY } from '../../constants'; import type { GetAgentPoliciesRequestSchema, @@ -56,25 +51,28 @@ import { import { createAgentPolicyWithPackages } from '../../services/agent_policy_create'; export async function populateAssignedAgentsCount( - esClient: ElasticsearchClient, - soClient: SavedObjectsClientContract, + agentClient: AgentClient, agentPolicies: AgentPolicy[] ) { await pMap( agentPolicies, (agentPolicy: GetAgentPoliciesResponseItem) => { - const totalAgents = getAgentsByKuery(esClient, soClient, { - showInactive: true, - perPage: 0, - page: 1, - kuery: `${AGENTS_PREFIX}.policy_id:${agentPolicy.id}`, - }).then(({ total }) => (agentPolicy.agents = total)); - const unprivilegedAgents = getAgentsByKuery(esClient, soClient, { - showInactive: true, - perPage: 0, - page: 1, - kuery: `${AGENTS_PREFIX}.policy_id:${agentPolicy.id} and ${UNPRIVILEGED_AGENT_KUERY}`, - }).then(({ total }) => (agentPolicy.unprivileged_agents = total)); + const totalAgents = agentClient + .listAgents({ + showInactive: true, + perPage: 0, + page: 1, + kuery: `${AGENTS_PREFIX}.policy_id:${agentPolicy.id}`, + }) + .then(({ total }) => (agentPolicy.agents = total)); + const unprivilegedAgents = agentClient + .listAgents({ + showInactive: true, + perPage: 0, + page: 1, + kuery: `${AGENTS_PREFIX}.policy_id:${agentPolicy.id} and ${UNPRIVILEGED_AGENT_KUERY}`, + }) + .then(({ total }) => (agentPolicy.unprivileged_agents = total)); return Promise.all([totalAgents, unprivilegedAgents]); }, { concurrency: 10 } @@ -121,9 +119,12 @@ export const getAgentPoliciesHandler: FleetRequestHandler< withPackagePolicies, esClient, ...restOfQuery, - withAgentCount: !noAgentCount, }); + if (fleetContext.authz.fleet.readAgents && !noAgentCount) { + await populateAssignedAgentsCount(fleetContext.agentClient.asCurrentUser, items); + } + const body: GetAgentPoliciesResponse = { items: !fleetContext.authz.fleet.readAgentPolicies ? items.map(sanitizeItemForReadAgentOnly) @@ -144,9 +145,8 @@ export const bulkGetAgentPoliciesHandler: FleetRequestHandler< TypeOf > = async (context, request, response) => { try { - const [coreContext, fleetContext] = await Promise.all([context.core, context.fleet]); + const fleetContext = await context.fleet; const soClient = fleetContext.internalSoClient; - const esClient = coreContext.elasticsearch.client.asInternalUser; const { full: withPackagePolicies = false, ignoreMissing = false, ids } = request.body; const items = await agentPolicyService.getByIDs(soClient, ids, { withPackagePolicies, @@ -157,8 +157,9 @@ export const bulkGetAgentPoliciesHandler: FleetRequestHandler< ? items.map(sanitizeItemForReadAgentOnly) : items, }; - - await populateAssignedAgentsCount(esClient, soClient, items); + if (fleetContext.authz.fleet.readAgents) { + await populateAssignedAgentsCount(fleetContext.agentClient.asCurrentUser, items); + } return response.ok({ body }); } catch (error) { @@ -179,12 +180,13 @@ export const getOneAgentPolicyHandler: FleetRequestHandler< > = async (context, request, response) => { try { const [coreContext, fleetContext] = await Promise.all([context.core, context.fleet]); - const esClient = coreContext.elasticsearch.client.asInternalUser; const soClient = coreContext.savedObjects.client; const agentPolicy = await agentPolicyService.get(soClient, request.params.agentPolicyId); if (agentPolicy) { - await populateAssignedAgentsCount(esClient, soClient, [agentPolicy]); + if (fleetContext.authz.fleet.readAgents) { + await populateAssignedAgentsCount(fleetContext.agentClient.asCurrentUser, [agentPolicy]); + } const body: GetOneAgentPolicyResponse = { item: !fleetContext.authz.fleet.readAgentPolicies ? sanitizeItemForReadAgentOnly(agentPolicy) diff --git a/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts b/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts index 60d8a2de45119..016a731d1c67e 100644 --- a/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts +++ b/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts @@ -7,6 +7,7 @@ import { type RequestHandler, SavedObjectsErrorHelpers } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; +import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; import type { GetEnrollmentAPIKeysRequestSchema, @@ -23,19 +24,25 @@ import type { import * as APIKeyService from '../../services/api_keys'; import { agentPolicyService } from '../../services/agent_policy'; import { defaultFleetErrorHandler, AgentPolicyNotFoundError } from '../../errors'; +import { appContextService } from '../../services'; export const getEnrollmentApiKeysHandler: RequestHandler< undefined, TypeOf > = async (context, request, response) => { + const { useSpaceAwareness } = appContextService.getExperimentalFeatures(); // Use kibana_system and depend on authz checks on HTTP layer to prevent abuse const esClient = (await context.core).elasticsearch.client.asInternalUser; + const soClient = (await context.core).savedObjects.client; try { const { items, total, page, perPage } = await APIKeyService.listEnrollmentApiKeys(esClient, { page: request.query.page, perPage: request.query.perPage, kuery: request.query.kuery, + spaceId: useSpaceAwareness + ? soClient.getCurrentNamespace() ?? DEFAULT_NAMESPACE_STRING + : undefined, }); const body: GetEnrollmentAPIKeysResponse = { list: items, // deprecated @@ -59,7 +66,7 @@ export const postEnrollmentApiKeyHandler: RequestHandler< const soClient = savedObjects.client; const esClient = elasticsearch.client.asInternalUser; try { - // validate policy id + // validate policy exists in the current space await agentPolicyService.get(soClient, request.body.policy_id).catch((err) => { if (SavedObjectsErrorHelpers.isNotFoundError(err)) { throw new AgentPolicyNotFoundError(`Agent policy "${request.body.policy_id}" not found`); @@ -85,9 +92,18 @@ export const postEnrollmentApiKeyHandler: RequestHandler< export const deleteEnrollmentApiKeyHandler: RequestHandler< TypeOf > = async (context, request, response) => { - const esClient = (await context.core).elasticsearch.client.asInternalUser; try { - await APIKeyService.deleteEnrollmentApiKey(esClient, request.params.keyId); + const { useSpaceAwareness } = appContextService.getExperimentalFeatures(); + const coreContext = await context.core; + const esClient = coreContext.elasticsearch.client.asInternalUser; + const currentNamespace = + coreContext.savedObjects.client.getCurrentNamespace() ?? DEFAULT_NAMESPACE_STRING; + await APIKeyService.deleteEnrollmentApiKey( + esClient, + request.params.keyId, + false, + useSpaceAwareness ? currentNamespace : undefined + ); const body: DeleteEnrollmentAPIKeyResponse = { action: 'deleted' }; @@ -106,9 +122,19 @@ export const getOneEnrollmentApiKeyHandler: RequestHandler< TypeOf > = async (context, request, response) => { // Use kibana_system and depend on authz checks on HTTP layer to prevent abuse - const esClient = (await context.core).elasticsearch.client.asInternalUser; + try { - const apiKey = await APIKeyService.getEnrollmentAPIKey(esClient, request.params.keyId); + const coreContext = await context.core; + const esClient = coreContext.elasticsearch.client.asInternalUser; + const currentNamespace = + coreContext.savedObjects.client.getCurrentNamespace() ?? DEFAULT_NAMESPACE_STRING; + const { useSpaceAwareness } = appContextService.getExperimentalFeatures(); + + const apiKey = await APIKeyService.getEnrollmentAPIKey( + esClient, + request.params.keyId, + useSpaceAwareness ? currentNamespace : undefined + ); const body: GetOneEnrollmentAPIKeyResponse = { item: apiKey }; return response.ok({ body }); diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts index 323c7b71ae487..bb9bf0b507ca9 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts @@ -14,6 +14,7 @@ import { RegistryError } from '../../errors'; import { createAppContextStartContractMock, createPackagePolicyServiceMock, + createUninstallTokenServiceMock, xpackMocks, } from '../../mocks'; import { agentServiceMock } from '../../services/agents/agent_service.mock'; @@ -45,6 +46,9 @@ describe('FleetSetupHandler', () => { context = { ...xpackMocks.createRequestHandlerContext(), fleet: { + uninstallTokenService: { + asCurrentUser: createUninstallTokenServiceMock(), + }, agentClient: { asCurrentUser: agentServiceMock.createClient(), asInternalUser: agentServiceMock.createClient(), @@ -129,6 +133,9 @@ describe('FleetStatusHandler', () => { context = { ...xpackMocks.createRequestHandlerContext(), fleet: { + uninstallTokenService: { + asCurrentUser: createUninstallTokenServiceMock(), + }, agentClient: { asCurrentUser: agentServiceMock.createClient(), asInternalUser: agentServiceMock.createClient(), diff --git a/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.test.ts b/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.test.ts index 31caa167ba59d..b51f19291c58a 100644 --- a/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.test.ts @@ -95,8 +95,8 @@ describe('uninstall token handlers', () => { >; const mockAgentPolicyService = agentPolicyService as jest.Mocked; - beforeEach(() => { - const uninstallTokenService = appContextService.getUninstallTokenService()!; + beforeEach(async () => { + const uninstallTokenService = (await context.fleet).uninstallTokenService.asCurrentUser; getTokenMetadataMock = uninstallTokenService.getTokenMetadata as jest.Mock; mockAgentPolicyService.list.mockResolvedValue({ items: [createAgentPolicyMock()], @@ -118,22 +118,6 @@ describe('uninstall token handlers', () => { }); }); - it('should return internal error when uninstallTokenService is unavailable', async () => { - appContextService.stop(); - appContextService.start({ - ...appContextStartContractMock, - // @ts-expect-error - uninstallTokenService: undefined, - }); - - await getUninstallTokensMetadataHandler(context, request, response); - - expect(response.customError).toHaveBeenCalledWith({ - statusCode: 500, - body: { message: 'Uninstall Token Service is unavailable.' }, - }); - }); - it('should return internal error when uninstallTokenService throws error', async () => { getTokenMetadataMock.mockRejectedValue(Error('something happened')); @@ -158,8 +142,8 @@ describe('uninstall token handlers', () => { let getTokenMock: jest.Mock; let request: KibanaRequest>; - beforeEach(() => { - const uninstallTokenService = appContextService.getUninstallTokenService()!; + beforeEach(async () => { + const uninstallTokenService = (await context.fleet).uninstallTokenService.asCurrentUser; getTokenMock = uninstallTokenService.getToken as jest.Mock; const requestOptions: GetUninstallTokenRequest = { @@ -183,22 +167,6 @@ describe('uninstall token handlers', () => { }); }); - it('should return internal error when uninstallTokenService is unavailable', async () => { - appContextService.stop(); - appContextService.start({ - ...appContextStartContractMock, - // @ts-expect-error - uninstallTokenService: undefined, - }); - - await getUninstallTokenHandler(context, request, response); - - expect(response.customError).toHaveBeenCalledWith({ - statusCode: 500, - body: { message: 'Uninstall Token Service is unavailable.' }, - }); - }); - it('should return internal error when uninstallTokenService throws error', async () => { getTokenMock.mockRejectedValue(Error('something happened')); diff --git a/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.ts b/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.ts index 189a1f8bc80f7..5e61d5b9b01a2 100644 --- a/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/uninstall_token/handlers.ts @@ -6,9 +6,8 @@ */ import type { TypeOf } from '@kbn/config-schema'; -import type { CustomHttpResponseOptions, ResponseError } from '@kbn/core-http-server'; -import { appContextService, agentPolicyService } from '../../services'; +import { agentPolicyService } from '../../services'; import type { FleetRequestHandler } from '../../types'; import type { GetUninstallTokensMetadataRequestSchema, @@ -18,33 +17,25 @@ import { defaultFleetErrorHandler } from '../../errors'; import type { GetUninstallTokenResponse } from '../../../common/types/rest_spec/uninstall_token'; import { AGENT_POLICY_SAVED_OBJECT_TYPE, SO_SEARCH_LIMIT } from '../../constants'; -const UNINSTALL_TOKEN_SERVICE_UNAVAILABLE_ERROR: CustomHttpResponseOptions = { - statusCode: 500, - body: { message: 'Uninstall Token Service is unavailable.' }, -}; - export const getUninstallTokensMetadataHandler: FleetRequestHandler< unknown, TypeOf > = async (context, request, response) => { - const uninstallTokenService = appContextService.getUninstallTokenService(); - if (!uninstallTokenService) { - return response.customError(UNINSTALL_TOKEN_SERVICE_UNAVAILABLE_ERROR); - } + try { + const [fleetContext, coreContext] = await Promise.all([context.fleet, context.core]); + const uninstallTokenService = fleetContext.uninstallTokenService.asCurrentUser; - const { page = 1, perPage = 20, policyId, search } = request.query; + const { page = 1, perPage = 20, policyId, search } = request.query; - if (policyId && search) { - return response.badRequest({ - body: { - message: 'Query parameters `policyId` and `search` cannot be used at the same time.', - }, - }); - } + if (policyId && search) { + return response.badRequest({ + body: { + message: 'Query parameters `policyId` and `search` cannot be used at the same time.', + }, + }); + } - try { - const fleetContext = await context.fleet; - const soClient = fleetContext.internalSoClient; + const soClient = coreContext.savedObjects.client; const { items: managedPolicies } = await agentPolicyService.list(soClient, { fields: ['id'], @@ -80,10 +71,8 @@ export const getUninstallTokensMetadataHandler: FleetRequestHandler< export const getUninstallTokenHandler: FleetRequestHandler< TypeOf > = async (context, request, response) => { - const uninstallTokenService = appContextService.getUninstallTokenService(); - if (!uninstallTokenService) { - return response.customError(UNINSTALL_TOKEN_SERVICE_UNAVAILABLE_ERROR); - } + const [fleetContext] = await Promise.all([context.fleet, context.core]); + const uninstallTokenService = fleetContext.uninstallTokenService.asCurrentUser; try { const { uninstallTokenId } = request.params; diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 5a084ac211e5e..d3d94fa581955 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -38,8 +38,6 @@ import { policyHasSyntheticsIntegration, } from '../../common/services'; -import { populateAssignedAgentsCount } from '../routes/agent_policy/handlers'; - import type { HTTPAuthorizationHeader } from '../../common/http_authorization_header'; import { @@ -349,7 +347,10 @@ class AgentPolicyService { options ); - await appContextService.getUninstallTokenService()?.generateTokenForPolicyId(newSo.id); + await appContextService + .getUninstallTokenService() + ?.scoped(soClient.getCurrentNamespace()) + ?.generateTokenForPolicyId(newSo.id); await this.triggerAgentPolicyUpdatedEvent(esClient, 'created', newSo.id, { skipDeploy: options.skipDeploy, spaceId: soClient.getCurrentNamespace(), @@ -485,8 +486,6 @@ class AgentPolicyService { kuery, withPackagePolicies = false, fields, - esClient, - withAgentCount = false, } = options; const baseFindParams = { @@ -526,6 +525,21 @@ class AgentPolicyService { agentPolicy.package_policies = (await packagePolicyService.findAllForAgentPolicy(soClient, agentPolicySO.id)) || []; } + if (options.withAgentCount) { + await getAgentsByKuery( + appContextService.getInternalUserESClient(), + appContextService.getInternalUserSOClientForSpaceId(agentPolicy.space_id), + { + showInactive: true, + perPage: 0, + page: 1, + kuery: `${AGENTS_PREFIX}.policy_id:${agentPolicy.id}`, + } + ).then(({ total }) => (agentPolicy.agents = total)); + } else { + agentPolicy.agents = 0; + } + return agentPolicy; }, { concurrency: 50 } @@ -538,11 +552,6 @@ class AgentPolicyService { savedObjectType: AGENT_POLICY_SAVED_OBJECT_TYPE, }); } - if (esClient && withAgentCount) { - await populateAssignedAgentsCount(esClient, soClient, agentPolicies); - } else { - agentPolicies.forEach((item) => (item.agents = 0)); - } return { items: agentPolicies, diff --git a/x-pack/plugins/fleet/server/services/agents/agent_service.test.ts b/x-pack/plugins/fleet/server/services/agents/agent_service.test.ts index 05ca64eaeaf7b..2db66f04d8a9b 100644 --- a/x-pack/plugins/fleet/server/services/agents/agent_service.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/agent_service.test.ts @@ -9,6 +9,12 @@ jest.mock('../security'); jest.mock('./crud'); jest.mock('./status'); jest.mock('./versions'); +jest.mock('../app_context', () => ({ + appContextService: { + getInternalUserSOClientForSpaceId: jest.fn(), + getSavedObjects: jest.fn(), + }, +})); import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; import { @@ -22,6 +28,7 @@ import { FleetUnauthorizedError } from '../../errors'; import { getAuthzFromRequest } from '../security'; import type { FleetAuthz } from '../../../common'; import { createFleetAuthzMock } from '../../../common/mocks'; +import { appContextService } from '../app_context'; import type { AgentClient } from './agent_service'; import { AgentServiceImpl } from './agent_service'; @@ -37,18 +44,24 @@ const mockGetAgentStatusForAgentPolicy = getAgentStatusForAgentPolicy as jest.Mo const mockgetLatestAvailableAgentVersion = getLatestAvailableAgentVersion as jest.Mock; describe('AgentService', () => { + let mockedScopedSoClient: jest.Mocked; + beforeEach(() => { jest.resetAllMocks(); + mockedScopedSoClient = savedObjectsClientMock.create(); + jest.mocked(appContextService.getSavedObjects).mockReturnValue({ + getScopedClient: jest.fn().mockReturnValue(mockedScopedSoClient), + } as any); + jest + .mocked(appContextService.getInternalUserSOClientForSpaceId) + .mockReturnValue(mockedScopedSoClient); }); describe('asScoped', () => { describe('without required privilege', () => { - const agentClient = new AgentServiceImpl( - elasticsearchServiceMock.createElasticsearchClient(), - savedObjectsClientMock.create() - ).asScoped(httpServerMock.createKibanaRequest()); + let agentClient: AgentClient; - beforeEach(() => + beforeEach(() => { mockGetAuthzFromRequest.mockReturnValue( Promise.resolve({ fleet: { @@ -77,8 +90,12 @@ describe('AgentService', () => { writeIntegrationPolicies: false, }, }) - ) - ); + ); + agentClient = new AgentServiceImpl( + elasticsearchServiceMock.createElasticsearchClient(), + savedObjectsClientMock.create() + ).asScoped(httpServerMock.createKibanaRequest()); + }); it('rejects on listAgents', async () => { await expect(agentClient.listAgents({ showInactive: true })).rejects.toThrowError( @@ -124,32 +141,65 @@ describe('AgentService', () => { describe('with required privilege', () => { const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); const mockSoClient = savedObjectsClientMock.create(); - const agentClient = new AgentServiceImpl(mockEsClient, mockSoClient).asScoped( - httpServerMock.createKibanaRequest() - ); beforeEach(() => mockGetAuthzFromRequest.mockReturnValue(Promise.resolve(createFleetAuthzMock())) ); + expectApisToCallServicesSuccessfully( + mockEsClient, + () => mockedScopedSoClient, + () => + new AgentServiceImpl(mockEsClient, mockSoClient).asScoped( + httpServerMock.createKibanaRequest() + ), + 'default' + ); + }); - expectApisToCallServicesSuccessfully(mockEsClient, mockSoClient, agentClient); + describe('with required privilege in a non default space', () => { + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + const mockSoClient = savedObjectsClientMock.create(); + + beforeEach(() => { + mockGetAuthzFromRequest.mockReturnValue(Promise.resolve(createFleetAuthzMock())); + jest.mocked(mockedScopedSoClient.getCurrentNamespace).mockReturnValue('test'); + }); + expectApisToCallServicesSuccessfully( + mockEsClient, + () => mockedScopedSoClient, + () => + new AgentServiceImpl(mockEsClient, mockSoClient).asScoped( + httpServerMock.createKibanaRequest() + ), + 'test' + ); }); }); describe('asInternalUser', () => { const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); const mockSoClient = savedObjectsClientMock.create(); - const agentClient = new AgentServiceImpl(mockEsClient, mockSoClient).asInternalUser; - - expectApisToCallServicesSuccessfully(mockEsClient, mockSoClient, agentClient); + expectApisToCallServicesSuccessfully( + mockEsClient, + () => mockSoClient, + () => new AgentServiceImpl(mockEsClient, mockSoClient).asInternalUser + ); }); }); function expectApisToCallServicesSuccessfully( mockEsClient: ElasticsearchClient, - mockSoClient: jest.Mocked, - agentClient: AgentClient + getExpectedSoClient: () => jest.Mocked, + agentClientFactory: () => AgentClient, + spaceId?: string ) { + let agentClient: AgentClient; + let mockSoClient: jest.Mocked; + beforeEach(() => { + mockSoClient = getExpectedSoClient(); + agentClient = agentClientFactory(); + }); + test('client.listAgents calls getAgentsByKuery and returns results', async () => { mockGetAgentsByKuery.mockResolvedValue('getAgentsByKuery success'); await expect(agentClient.listAgents({ showInactive: true })).resolves.toEqual( @@ -157,6 +207,7 @@ function expectApisToCallServicesSuccessfully( ); expect(mockGetAgentsByKuery).toHaveBeenCalledWith(mockEsClient, mockSoClient, { showInactive: true, + spaceId, }); }); @@ -183,7 +234,8 @@ function expectApisToCallServicesSuccessfully( mockEsClient, mockSoClient, 'foo-id', - 'foo-filter' + 'foo-filter', + spaceId ); }); diff --git a/x-pack/plugins/fleet/server/services/agents/agent_service.ts b/x-pack/plugins/fleet/server/services/agents/agent_service.ts index 512db893d1c63..9af97cc307c08 100644 --- a/x-pack/plugins/fleet/server/services/agents/agent_service.ts +++ b/x-pack/plugins/fleet/server/services/agents/agent_service.ts @@ -19,11 +19,12 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SortResults } from '@elastic/elasticsearch/lib/api/types'; +import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; + import type { AgentStatus, ListWithKuery } from '../../types'; import type { Agent, GetAgentStatusResponse } from '../../../common/types'; - import { getAuthzFromRequest } from '../security'; - +import { appContextService } from '../app_context'; import { FleetUnauthorizedError } from '../../errors'; import { getAgentsByKuery, getAgentById } from './crud'; @@ -88,6 +89,7 @@ export interface AgentClient { total: number; page: number; perPage: number; + statusSummary?: Record; aggregations?: Record; }>; @@ -104,7 +106,8 @@ class AgentClientImpl implements AgentClient { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly soClient: SavedObjectsClientContract, - private readonly preflightCheck?: () => void | Promise + private readonly preflightCheck?: () => void | Promise, + private readonly spaceId?: string ) {} public async listAgents( @@ -114,7 +117,10 @@ class AgentClientImpl implements AgentClient { } ) { await this.#runPreflight(); - return getAgentsByKuery(this.internalEsClient, this.soClient, options); + return getAgentsByKuery(this.internalEsClient, this.soClient, { + ...options, + spaceId: this.spaceId, + }); } public async getAgent(agentId: string) { @@ -133,7 +139,8 @@ class AgentClientImpl implements AgentClient { this.internalEsClient, this.soClient, agentPolicyId, - filterKuery + filterKuery, + this.spaceId ); } @@ -161,14 +168,23 @@ export class AgentServiceImpl implements AgentService { public asScoped(req: KibanaRequest) { const preflightCheck = async () => { const authz = await getAuthzFromRequest(req); - if (!authz.fleet.all) { + if (!authz.fleet.all && !authz.fleet.readAgents) { throw new FleetUnauthorizedError( `User does not have adequate permissions to access Fleet agents.` ); } }; - return new AgentClientImpl(this.internalEsClient, this.soClient, preflightCheck); + const soClient = appContextService.getInternalUserSOClientForSpaceId( + appContextService.getSavedObjects().getScopedClient(req).getCurrentNamespace() + ); + + return new AgentClientImpl( + this.internalEsClient, + soClient, + preflightCheck, + soClient.getCurrentNamespace() ?? DEFAULT_NAMESPACE_STRING + ); } public get asInternalUser() { diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index 67b4b964796a6..e6bcd5f954f2e 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -4,16 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + +import { groupBy } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SortResults } from '@elastic/elasticsearch/lib/api/types'; import type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; import type { KueryNode } from '@kbn/es-query'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; - +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { groupBy } from 'lodash'; - import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { appContextService, agentPolicyService } from '..'; import type { AgentStatus, FleetServerAgent } from '../../../common/types'; @@ -37,7 +37,9 @@ import { getLatestAvailableAgentVersion } from './versions'; const INACTIVE_AGENT_CONDITION = `status:inactive OR status:unenrolled`; const ACTIVE_AGENT_CONDITION = `NOT (${INACTIVE_AGENT_CONDITION})`; -function _joinFilters(filters: Array): KueryNode | undefined { +export function _joinFilters( + filters: Array +): KueryNode | undefined { try { return filters .filter((filter) => filter !== undefined) @@ -214,6 +216,7 @@ export async function getAgentsByKuery( soClient: SavedObjectsClientContract, options: ListWithKuery & { showInactive: boolean; + spaceId?: string; getStatusSummary?: boolean; sortField?: string; sortOrder?: 'asc' | 'desc'; @@ -241,9 +244,19 @@ export async function getAgentsByKuery( searchAfter, pitId, aggregations, + spaceId, } = options; const filters = []; + const useSpaceAwareness = appContextService.getExperimentalFeatures()?.useSpaceAwareness; + if (useSpaceAwareness && spaceId) { + if (spaceId === DEFAULT_SPACE_ID) { + filters.push(`namespaces:"${DEFAULT_SPACE_ID}" or not namespaces:*`); + } else { + filters.push(`namespaces:"${spaceId}"`); + } + } + if (kuery && kuery !== '') { filters.push(kuery); } diff --git a/x-pack/plugins/fleet/server/services/agents/helpers.ts b/x-pack/plugins/fleet/server/services/agents/helpers.ts index 21e4e864e3b6f..2ddad0c24abab 100644 --- a/x-pack/plugins/fleet/server/services/agents/helpers.ts +++ b/x-pack/plugins/fleet/server/services/agents/helpers.ts @@ -60,6 +60,7 @@ export function searchHitToAgent( const agent: Agent = { id: hit._id, type: hit._source?.type!, + namespaces: hit._source?.namespaces, active: hit._source?.active!, enrolled_at: hit._source?.enrolled_at!, unenrolled_at: hit._source?.unenrolled_at!, diff --git a/x-pack/plugins/fleet/server/services/agents/status.ts b/x-pack/plugins/fleet/server/services/agents/status.ts index f4d0e312ba027..31fb9f5fe9218 100644 --- a/x-pack/plugins/fleet/server/services/agents/status.ts +++ b/x-pack/plugins/fleet/server/services/agents/status.ts @@ -6,10 +6,9 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; - import { toElasticsearchQuery } from '@kbn/es-query'; import { fromKueryExpression } from '@kbn/es-query'; - +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import type { AggregationsTermsAggregateBase, AggregationsTermsBucketBase, @@ -45,13 +44,27 @@ export async function getAgentStatusForAgentPolicy( esClient: ElasticsearchClient, soClient: SavedObjectsClientContract, agentPolicyId?: string, - filterKuery?: string + filterKuery?: string, + spaceId?: string ) { const logger = appContextService.getLogger(); const runtimeFields = await buildAgentStatusRuntimeField(soClient); const clauses: QueryDslQueryContainer[] = []; + const useSpaceAwareness = appContextService.getExperimentalFeatures()?.useSpaceAwareness; + if (useSpaceAwareness && spaceId) { + if (spaceId === DEFAULT_SPACE_ID) { + clauses.push( + toElasticsearchQuery( + fromKueryExpression(`namespaces:"${DEFAULT_SPACE_ID}" or not namespaces:*`) + ) + ); + } else { + clauses.push(toElasticsearchQuery(fromKueryExpression(`namespaces:"${spaceId}"`))); + } + } + if (filterKuery) { const kueryAsElasticsearchQuery = toElasticsearchQuery( fromKueryExpression(removeSOAttributes(filterKuery)) diff --git a/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts b/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts index d962279f0ca32..b118b8ff03ac8 100644 --- a/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts @@ -22,6 +22,7 @@ jest.mock('../app_context', () => { getLogger: () => loggerMock.create(), getConfig: () => {}, getMessageSigningService: jest.fn(), + getExperimentalFeatures: jest.fn().mockResolvedValue({}), }, }; }); diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.test.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.test.ts index ef2209c173510..6d37dd44a7f5e 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.test.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.test.ts @@ -17,7 +17,11 @@ import { agentPolicyService } from '../agent_policy'; import { auditLoggingService } from '../audit_logging'; import { appContextService } from '../app_context'; -import { deleteEnrollmentApiKey, generateEnrollmentAPIKey } from './enrollment_api_key'; +import { + deleteEnrollmentApiKey, + generateEnrollmentAPIKey, + getEnrollmentAPIKey, +} from './enrollment_api_key'; jest.mock('../audit_logging'); jest.mock('../agent_policy'); @@ -147,4 +151,49 @@ describe('enrollment api keys', () => { }); }); }); + + describe('getEnrollementApiKey', () => { + it('should not allow to retrieve a key in the current space', async () => { + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + esClient.get.mockResolvedValue({ + _id: 'test-id', + _index: ENROLLMENT_API_KEYS_INDEX, + _source: { + active: true, + created_at: new Date().toISOString(), + api_key_id: 'test-enrollment-api-key-id', + namespaces: ['test'], + }, + found: true, + }); + + const enrollmentKey = await getEnrollmentAPIKey( + esClient, + 'test-enrollment-api-key-id', + 'test' + ); + expect(enrollmentKey).toBeDefined(); + }); + it('should not allow to retrieve a key in a different space', async () => { + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + esClient.get.mockResolvedValue({ + _id: 'test-id', + _index: ENROLLMENT_API_KEYS_INDEX, + _source: { + active: true, + created_at: new Date().toISOString(), + api_key_id: 'test-enrollment-api-key-id', + }, + found: true, + }); + + await expect( + getEnrollmentAPIKey(esClient, 'test-enrollment-api-key-id', 'test') + ).rejects.toThrowError( + 'Enrollment api key test-enrollment-api-key-id not found in namespace' + ); + }); + }); }); diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts index 02e1e9e25e194..e89917143732f 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts @@ -11,8 +11,8 @@ import { i18n } from '@kbn/i18n'; import { errors } from '@elastic/elasticsearch'; import type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; -import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; - +import { toElasticsearchQuery } from '@kbn/es-query'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import type { ESSearchResponse as SearchResponse } from '@kbn/es-types'; import type { EnrollmentAPIKey, FleetServerEnrollmentAPIKey } from '../../types'; @@ -20,9 +20,8 @@ import { FleetError, EnrollmentKeyNameExistsError, EnrollmentKeyNotFoundError } import { ENROLLMENT_API_KEYS_INDEX } from '../../constants'; import { agentPolicyService } from '../agent_policy'; import { escapeSearchQueryPhrase } from '../saved_object'; - import { auditLoggingService } from '../audit_logging'; - +import { _joinFilters } from '../agents'; import { appContextService } from '../app_context'; import { invalidateAPIKeys } from './security'; @@ -38,10 +37,38 @@ export async function listEnrollmentApiKeys( kuery?: string; query?: ReturnType; showInactive?: boolean; + spaceId?: string; } ): Promise<{ items: EnrollmentAPIKey[]; total: any; page: any; perPage: any }> { - const { page = 1, perPage = 20, kuery } = options; - const query = options.query ?? (kuery && toElasticsearchQuery(fromKueryExpression(kuery))); + const { page = 1, perPage = 20, kuery, spaceId } = options; + // const query = options.query ?? (kuery && toElasticsearchQuery(fromKueryExpression(kuery))); + + let query: ReturnType | undefined; + if (options.query && spaceId) { + throw new Error('not implemented (query should only be used in Fleet internal usage)'); + } + if (!options.query) { + const filters: string[] = []; + + if (kuery) { + filters.push(kuery); + } + + const useSpaceAwareness = appContextService.getExperimentalFeatures()?.useSpaceAwareness; + if (useSpaceAwareness && spaceId) { + if (spaceId === DEFAULT_SPACE_ID) { + // TODO use constant + filters.push(`namespaces:"${DEFAULT_SPACE_ID}" or not namespaces:*`); + } else { + filters.push(`namespaces:"${spaceId}"`); + } + } + + const kueryNode = _joinFilters(filters); + query = kueryNode ? toElasticsearchQuery(kueryNode) : undefined; + } else { + query = options.query; + } const res = await esClient.search>({ index: ENROLLMENT_API_KEYS_INDEX, @@ -80,7 +107,8 @@ export async function hasEnrollementAPIKeysForPolicy( export async function getEnrollmentAPIKey( esClient: ElasticsearchClient, - id: string + id: string, + spaceId?: string ): Promise { try { const body = await esClient.get({ @@ -88,6 +116,16 @@ export async function getEnrollmentAPIKey( id, }); + if (spaceId) { + if (spaceId === DEFAULT_SPACE_ID) { + if (body._source?.namespaces && !body._source?.namespaces.includes(DEFAULT_SPACE_ID)) { + throw new EnrollmentKeyNotFoundError(`Enrollment api key ${id} not found in namespace`); + } + } else if (!body._source?.namespaces?.includes(spaceId)) { + throw new EnrollmentKeyNotFoundError(`Enrollment api key ${id} not found in namespace`); + } + } + // @ts-expect-error esDocToEnrollmentApiKey doesn't accept optional _source return esDocToEnrollmentApiKey(body); } catch (e) { @@ -106,12 +144,13 @@ export async function getEnrollmentAPIKey( export async function deleteEnrollmentApiKey( esClient: ElasticsearchClient, id: string, - forceDelete = false + forceDelete = false, + spaceId?: string ) { const logger = appContextService.getLogger(); logger.debug(`Deleting enrollment API key ${id}`); - const enrollmentApiKey = await getEnrollmentAPIKey(esClient, id); + const enrollmentApiKey = await getEnrollmentAPIKey(esClient, id, spaceId); auditLoggingService.writeCustomAuditLog({ message: `User deleting enrollment API key [id=${enrollmentApiKey.id}] [api_key_id=${enrollmentApiKey.api_key_id}]`, diff --git a/x-pack/plugins/fleet/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts index 533b57f6f7653..9770d6a696e85 100644 --- a/x-pack/plugins/fleet/server/services/app_context.ts +++ b/x-pack/plugins/fleet/server/services/app_context.ts @@ -22,6 +22,7 @@ import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server'; import type { EncryptedSavedObjectsClient, EncryptedSavedObjectsPluginSetup, + EncryptedSavedObjectsPluginStart, } from '@kbn/encrypted-saved-objects-plugin/server'; import type { SecurityPluginStart, SecurityPluginSetup } from '@kbn/security-plugin/server'; @@ -47,14 +48,16 @@ import type { } from '../types'; import type { FleetAppContext } from '../plugin'; import type { TelemetryEventsSender } from '../telemetry/sender'; +import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE } from '../constants'; import type { MessageSigningServiceInterface } from '..'; -import type { BulkActionsResolver } from './agents'; -import type { UninstallTokenServiceInterface } from './security/uninstall_token_service'; +import type { BulkActionsResolver } from './agents/bulk_actions_resolver'; +import { type UninstallTokenServiceInterface } from './security/uninstall_token_service'; class AppContextService { private encryptedSavedObjects: EncryptedSavedObjectsClient | undefined; private encryptedSavedObjectsSetup: EncryptedSavedObjectsPluginSetup | undefined; + private encryptedSavedObjectsStart: EncryptedSavedObjectsPluginStart | undefined; private data: DataPluginStart | undefined; private esClient: ElasticsearchClient | undefined; private experimentalFeatures?: ExperimentalFeatures; @@ -80,6 +83,7 @@ class AppContextService { public start(appContext: FleetAppContext) { this.data = appContext.data; this.esClient = appContext.elasticsearch.client.asInternalUser; + this.encryptedSavedObjectsStart = appContext.encryptedSavedObjectsStart; this.encryptedSavedObjects = appContext.encryptedSavedObjectsStart?.getClient(); this.encryptedSavedObjectsSetup = appContext.encryptedSavedObjectsSetup; this.securitySetup = appContext.securitySetup; @@ -190,6 +194,7 @@ class AppContextService { // soClient as kibana internal users, be careful on how you use it, security is not enabled return appContextService.getSavedObjects().getScopedClient(request, { + includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], excludedExtensions: [SECURITY_EXTENSION_ID], }); } @@ -209,6 +214,7 @@ class AppContextService { // soClient as kibana internal users, be careful on how you use it, security is not enabled return appContextService.getSavedObjects().getScopedClient(request, { + includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], excludedExtensions: [SECURITY_EXTENSION_ID], }); } @@ -253,6 +259,10 @@ class AppContextService { return this.encryptedSavedObjectsSetup; } + public getEncryptedSavedObjectsStart() { + return this.encryptedSavedObjectsStart; + } + public getKibanaVersion() { return this.kibanaVersion; } diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts index b6dc2fb859d25..21caf5088f457 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts @@ -300,6 +300,9 @@ jest.mock('./app_context', () => ({ ), getUninstallTokenService: () => ({ generateTokenForPolicyId: jest.fn(), + scoped: jest.fn().mockReturnValue({ + generateTokenForPolicyId: jest.fn(), + }), }), getExternalCallbacks: jest.fn(), getCloud: jest.fn(), diff --git a/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts b/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts index 944eab70d23c3..211026bf6e487 100644 --- a/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts +++ b/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts @@ -32,12 +32,11 @@ import type { import { isResponseError } from '@kbn/es-errors'; -import type { AgentPolicySOAttributes } from '../../../types'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; +import type { AgentPolicySOAttributes } from '../../../types'; import { UninstallTokenError } from '../../../../common/errors'; - import type { GetUninstallTokensMetadataResponse } from '../../../../common/types/rest_spec/uninstall_token'; - import type { UninstallToken, UninstallTokenMetadata, @@ -168,18 +167,37 @@ export interface UninstallTokenServiceInterface { * */ checkTokenValidityForAllPolicies(): Promise; + + scoped(spaceId?: string): UninstallTokenServiceInterface; } export class UninstallTokenService implements UninstallTokenServiceInterface { private _soClient: SavedObjectsClientContract | undefined; + private isScoped = false; + + constructor( + private esoClient: EncryptedSavedObjectsClient, + soClient?: SavedObjectsClientContract + ) { + if (soClient) { + this._soClient = soClient; + this.isScoped = true; + } + } - constructor(private esoClient: EncryptedSavedObjectsClient) {} + public scoped(spaceId?: string) { + return new UninstallTokenService( + this.esoClient, + appContextService.getInternalUserSOClientForSpaceId(spaceId) + ); + } public async getToken(id: string): Promise { - const filter = `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.id: "${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:${id}"`; - + const namespacePrefix = this.soClient.getCurrentNamespace() + ? `${this.soClient.getCurrentNamespace()}:` + : ''; + const filter = `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.id: "${namespacePrefix}${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:${id}"`; const tokenObjects = await this.getDecryptedTokenObjects({ filter }); - return tokenObjects.length === 1 ? this.convertTokenObjectToToken( await this.getPolicyIdNameDictionary([tokenObjects[0].attributes.policy_id]), @@ -262,8 +280,11 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { this.assertCreatedAt(_source.created_at); const policyId = _source[UNINSTALL_TOKENS_SAVED_OBJECT_TYPE].policy_id; + const namespacePrefix = this.soClient.getCurrentNamespace() + ? `${this.soClient.getCurrentNamespace()}:` + : ''; return { - id: _id.replace(`${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:`, ''), + id: _id.replace(`${namespacePrefix}${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:`, ''), policy_id: policyId, policy_name: policyIdNameDictionary[policyId] ?? null, created_at: _source.created_at, @@ -356,6 +377,9 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { { type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, perPage: SO_SEARCH_LIMIT, + namespaces: this.isScoped + ? [this.soClient.getCurrentNamespace() || DEFAULT_SPACE_ID] + : undefined, ...options, } ); @@ -401,7 +425,6 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { exclude?: AggregationsTermsExclude ): Promise>> { const bucketSize = 10000; - const query: SavedObjectsCreatePointInTimeFinderOptions = { type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, perPage: 0, @@ -451,7 +474,6 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { // sorting and paginating buckets is done here instead of ES, // because SO query doesn't support `bucket_sort` aggResults.sort((a, b) => getCreatedAt(b) - getCreatedAt(a)); - return aggResults.map((bucket) => bucket.latest.hits.hits[0]); } @@ -578,6 +600,9 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { await this.soClient.bulkCreate>( policyIdsBatch.map((policyId) => ({ type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, + initialNamespaces: this.soClient.getCurrentNamespace() + ? [this.soClient.getCurrentNamespace() as string] + : undefined, attributes: this.isEncryptionAvailable ? { policy_id: policyId, diff --git a/x-pack/plugins/fleet/server/types/request_context.ts b/x-pack/plugins/fleet/server/types/request_context.ts index bc0e1c8886bff..dac735c9a3ed1 100644 --- a/x-pack/plugins/fleet/server/types/request_context.ts +++ b/x-pack/plugins/fleet/server/types/request_context.ts @@ -17,6 +17,7 @@ import type { import type { FleetAuthz } from '../../common/authz'; import type { AgentClient } from '../services'; import type { PackagePolicyClient } from '../services/package_policy_service'; +import type { UninstallTokenServiceInterface } from '../services/security/uninstall_token_service'; /** @internal */ export type FleetRequestHandlerContext = CustomRequestHandlerContext<{ @@ -32,6 +33,9 @@ export type FleetRequestHandlerContext = CustomRequestHandlerContext<{ asCurrentUser: PackagePolicyClient; asInternalUser: PackagePolicyClient; }; + uninstallTokenService: { + asCurrentUser: UninstallTokenServiceInterface; + }; /** * Saved Objects client configured to use kibana_system privileges instead of end-user privileges. Should only be * used by routes that have additional privilege checks for authorization (such as requiring superuser). diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/agent_policies.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/agent_policies.ts new file mode 100644 index 0000000000000..7ab4e86448bde --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/agent_policies.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { CreateAgentPolicyResponse } from '@kbn/fleet-plugin/common'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { SpaceTestApiClient } from './api_helper'; +import { cleanFleetIndices } from './helpers'; +import { setupTestSpaces, TEST_SPACE_1 } from './space_helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esClient = getService('es'); + const kibanaServer = getService('kibanaServer'); + + describe('agent policies', async function () { + skipIfNoDockerRegistry(providerContext); + const apiClient = new SpaceTestApiClient(supertest); + + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + let defaultSpacePolicy1: CreateAgentPolicyResponse; + let spaceTest1Policy1: CreateAgentPolicyResponse; + let spaceTest1Policy2: CreateAgentPolicyResponse; + before(async () => { + const [_defaultSpacePolicy1, _spaceTest1Policy1, _spaceTest1Policy2] = await Promise.all([ + apiClient.createAgentPolicy(), + apiClient.createAgentPolicy(TEST_SPACE_1), + apiClient.createAgentPolicy(TEST_SPACE_1), + ]); + defaultSpacePolicy1 = _defaultSpacePolicy1; + spaceTest1Policy1 = _spaceTest1Policy1; + spaceTest1Policy2 = _spaceTest1Policy2; + }); + + describe('GET /agent_policies', () => { + it('should return policies in a specific space', async () => { + const agentPolicies = await apiClient.getAgentPolicies(TEST_SPACE_1); + expect(agentPolicies.total).to.eql(2); + const policyIds = agentPolicies.items?.map((item) => item.id); + expect(policyIds).to.contain(spaceTest1Policy1.item.id); + expect(policyIds).to.contain(spaceTest1Policy2.item.id); + expect(policyIds).not.to.contain(defaultSpacePolicy1.item.id); + }); + + it('should return policies in default space', async () => { + const agentPolicies = await apiClient.getAgentPolicies(); + expect(agentPolicies.total).to.eql(1); + const policyIds = agentPolicies.items?.map((item) => item.id); + expect(policyIds).not.to.contain(spaceTest1Policy1.item.id); + expect(policyIds).not.contain(spaceTest1Policy2.item.id); + expect(policyIds).to.contain(defaultSpacePolicy1.item.id); + }); + }); + + describe('GET /agent_policies/{id}', () => { + it('should allow to access a policy in a specific space', async () => { + await apiClient.getAgentPolicy(spaceTest1Policy1.item.id, TEST_SPACE_1); + }); + it('should not allow to get a policy from a different space from the default space', async () => { + let err: Error | undefined; + try { + await apiClient.getAgentPolicy(spaceTest1Policy1.item.id); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + + it('should not allow to get an default space policy from a different space', async () => { + let err: Error | undefined; + try { + await apiClient.getAgentPolicy(defaultSpacePolicy1.item.id, TEST_SPACE_1); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/agents.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/agents.ts new file mode 100644 index 0000000000000..73c2675d7b2d5 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/agents.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { CreateAgentPolicyResponse } from '@kbn/fleet-plugin/common'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { SpaceTestApiClient } from './api_helper'; +import { cleanFleetIndices } from './helpers'; +import { setupTestSpaces, TEST_SPACE_1 } from './space_helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esClient = getService('es'); + const kibanaServer = getService('kibanaServer'); + const createFleetAgent = async (agentPolicyId: string, spaceId?: string) => { + const agentResponse = await esClient.index({ + index: '.fleet-agents', + refresh: true, + body: { + access_api_key_id: 'api-key-3', + active: true, + policy_id: agentPolicyId, + policy_revision_idx: 1, + last_checkin_status: 'online', + type: 'PERMANENT', + local_metadata: { + host: { hostname: 'host123' }, + elastic: { agent: { version: '8.15.0' } }, + }, + user_provided_metadata: {}, + enrolled_at: new Date().toISOString(), + last_checkin: new Date().toISOString(), + tags: ['tag1'], + namespaces: spaceId ? [spaceId] : undefined, + }, + }); + + return agentResponse._id; + }; + describe('agents', async function () { + skipIfNoDockerRegistry(providerContext); + const apiClient = new SpaceTestApiClient(supertest); + + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + let defaultSpacePolicy1: CreateAgentPolicyResponse; + let spaceTest1Policy1: CreateAgentPolicyResponse; + let spaceTest1Policy2: CreateAgentPolicyResponse; + + let defaultSpaceAgent1: string; + let defaultSpaceAgent2: string; + let testSpaceAgent1: string; + let testSpaceAgent2: string; + + before(async () => { + const [_defaultSpacePolicy1, _spaceTest1Policy1, _spaceTest1Policy2] = await Promise.all([ + apiClient.createAgentPolicy(), + apiClient.createAgentPolicy(TEST_SPACE_1), + apiClient.createAgentPolicy(TEST_SPACE_1), + ]); + defaultSpacePolicy1 = _defaultSpacePolicy1; + spaceTest1Policy1 = _spaceTest1Policy1; + spaceTest1Policy2 = _spaceTest1Policy2; + + const [_defaultSpaceAgent1, _defaultSpaceAgent2, _testSpaceAgent1, _testSpaceAgent2] = + await Promise.all([ + createFleetAgent(defaultSpacePolicy1.item.id, 'default'), + createFleetAgent(defaultSpacePolicy1.item.id), + createFleetAgent(spaceTest1Policy1.item.id, TEST_SPACE_1), + createFleetAgent(spaceTest1Policy2.item.id, TEST_SPACE_1), + ]); + + defaultSpaceAgent1 = _defaultSpaceAgent1; + defaultSpaceAgent2 = _defaultSpaceAgent2; + testSpaceAgent1 = _testSpaceAgent1; + testSpaceAgent2 = _testSpaceAgent2; + }); + + describe('GET /agents', () => { + it('should return agents in a specific space', async () => { + const agents = await apiClient.getAgents(TEST_SPACE_1); + expect(agents.total).to.eql(2); + const agentIds = agents.items?.map((item) => item.id); + expect(agentIds).to.contain(testSpaceAgent1); + expect(agentIds).to.contain(testSpaceAgent2); + }); + + it('should return agents in default space', async () => { + const agents = await apiClient.getAgents(); + expect(agents.total).to.eql(2); + const agentIds = agents.items?.map((item) => item.id); + expect(agentIds).to.contain(defaultSpaceAgent1); + expect(agentIds).to.contain(defaultSpaceAgent2); + }); + }); + + describe('GET /agents/{id}', () => { + it('should allow to retrieve agent in the same space', async () => { + await apiClient.getAgent(testSpaceAgent1, TEST_SPACE_1); + }); + + it('should not allow to get an agent from a different space from the default space', async () => { + let err: Error | undefined; + try { + await apiClient.getAgent(testSpaceAgent1); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts new file mode 100644 index 0000000000000..cff3d3ddb637b --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts @@ -0,0 +1,142 @@ +/* + * Copyright 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 { v4 as uuidV4 } from 'uuid'; +import type { Agent } from 'supertest'; +import { + CreateAgentPolicyResponse, + GetAgentPoliciesResponse, + GetAgentsResponse, + GetOneAgentPolicyResponse, + GetOneAgentResponse, +} from '@kbn/fleet-plugin/common'; +import { + GetEnrollmentAPIKeysResponse, + GetOneEnrollmentAPIKeyResponse, + PostEnrollmentAPIKeyResponse, + PostEnrollmentAPIKeyRequest, +} from '@kbn/fleet-plugin/common/types'; +import { + GetUninstallTokenResponse, + GetUninstallTokensMetadataResponse, +} from '@kbn/fleet-plugin/common/types/rest_spec/uninstall_token'; + +export class SpaceTestApiClient { + constructor(private readonly supertest: Agent) {} + private getBaseUrl(spaceId?: string) { + return spaceId ? `/s/${spaceId}` : ''; + } + // Agent policies + async createAgentPolicy(spaceId?: string): Promise { + const { body: res } = await this.supertest + .post(`${this.getBaseUrl(spaceId)}/api/fleet/agent_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `test ${uuidV4()}`, + description: '', + namespace: 'default', + inactivity_timeout: 24 * 1000, + }) + .expect(200); + + return res; + } + async deleteAgentPolicy(agentPolicyId: string, spaceId?: string) { + await this.supertest + .post(`${this.getBaseUrl(spaceId)}/api/fleet/agent_policies/delete`) + .send({ + agentPolicyId, + }) + .set('kbn-xsrf', 'xxxx') + .expect(200); + } + async getAgentPolicy(policyId: string, spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/agent_policies/${policyId}`) + .expect(200); + + return res; + } + async getAgentPolicies(spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/agent_policies`) + .expect(200); + + return res; + } + // Enrollmennt API Keys + async getEnrollmentApiKey( + keyId: string, + spaceId?: string + ): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/enrollment_api_keys/${keyId}`) + .expect(200); + + return res; + } + async getEnrollmentApiKeys(spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/enrollment_api_keys`) + .expect(200); + + return res; + } + async deleteEnrollmentApiKey( + keyId: string, + spaceId?: string + ): Promise { + const { body: res } = await this.supertest + .delete(`${this.getBaseUrl(spaceId)}/api/fleet/enrollment_api_keys/${keyId}`) + .set('kbn-xsrf', 'xxxx') + .expect(200); + + return res; + } + async postEnrollmentApiKeys( + body: PostEnrollmentAPIKeyRequest['body'], + spaceId?: string + ): Promise { + const { body: res } = await this.supertest + .post(`${this.getBaseUrl(spaceId)}/api/fleet/enrollment_api_keys`) + .set('kbn-xsrf', 'xxxx') + .send(body) + .expect(200); + + return res; + } + // Uninstall tokens + async getUninstallTokens(spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/uninstall_tokens`) + .expect(200); + + return res; + } + async getUninstallToken(tokenId: string, spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/uninstall_tokens/${tokenId}`) + .expect(200); + + return res; + } + // Agents + async getAgent(agentId: string, spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/agents/${agentId}`) + .expect(200); + + return res; + } + async getAgents(spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/api/fleet/agents`) + .expect(200); + + return res; + } +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_api_keys.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_api_keys.ts new file mode 100644 index 0000000000000..13238acb3917c --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_api_keys.ts @@ -0,0 +1,196 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { CreateAgentPolicyResponse } from '@kbn/fleet-plugin/common'; +import { type EnrollmentAPIKey } from '@kbn/fleet-plugin/common/types'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { SpaceTestApiClient } from './api_helper'; +import { cleanFleetIndices } from './helpers'; +import { setupTestSpaces, TEST_SPACE_1 } from './space_helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esClient = getService('es'); + const kibanaServer = getService('kibanaServer'); + + describe('enrollment api keys', async function () { + skipIfNoDockerRegistry(providerContext); + const apiClient = new SpaceTestApiClient(supertest); + + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + + let defaultSpacePolicy1: CreateAgentPolicyResponse; + let spaceTest1Policy1: CreateAgentPolicyResponse; + let spaceTest1Policy2: CreateAgentPolicyResponse; + let defaultSpaceEnrollmentKey1: EnrollmentAPIKey; + let spaceTest1EnrollmentKey1: EnrollmentAPIKey; + // Create agent policies it should create a enrollment key for every keys + before(async () => { + const [_defaultSpacePolicy1, _spaceTest1Policy1, _spaceTest1Policy2] = await Promise.all([ + apiClient.createAgentPolicy(), + apiClient.createAgentPolicy(TEST_SPACE_1), + apiClient.createAgentPolicy(TEST_SPACE_1), + ]); + defaultSpacePolicy1 = _defaultSpacePolicy1; + spaceTest1Policy1 = _spaceTest1Policy1; + spaceTest1Policy2 = _spaceTest1Policy2; + + const space1ApiKeys = await apiClient.getEnrollmentApiKeys(TEST_SPACE_1); + const defaultSpaceApiKeys = await apiClient.getEnrollmentApiKeys(); + defaultSpaceEnrollmentKey1 = defaultSpaceApiKeys.items[0]; + spaceTest1EnrollmentKey1 = space1ApiKeys.items[0]; + }); + + describe('read APIs', () => { + describe('GET /enrollment_api_keys', () => { + it('should return enrolmment keys in a specific space', async () => { + const apiKeys = await apiClient.getEnrollmentApiKeys(TEST_SPACE_1); + expect(apiKeys.total).to.eql(2); + const policyIds = apiKeys.items?.map((item) => item.policy_id); + expect(policyIds).to.contain(spaceTest1Policy1.item.id); + expect(policyIds).to.contain(spaceTest1Policy2.item.id); + expect(policyIds).not.to.contain(defaultSpacePolicy1.item.id); + }); + + it('should return enrolmment keys in default space', async () => { + const apiKeys = await apiClient.getEnrollmentApiKeys(); + expect(apiKeys.total).to.eql(1); + const policyIds = apiKeys.items?.map((item) => item.policy_id); + expect(policyIds).not.to.contain(spaceTest1Policy1.item.id); + expect(policyIds).not.contain(spaceTest1Policy2.item.id); + expect(policyIds).to.contain(defaultSpacePolicy1.item.id); + }); + }); + + describe('GET /enrollment_api_keys/{id}', () => { + it('should allow to access a enrollment keu in a specific space', async () => { + await apiClient.getEnrollmentApiKey(spaceTest1EnrollmentKey1.id, TEST_SPACE_1); + }); + it('should not allow to get an enrolmment key from a different space from the default space', async () => { + let err: Error | undefined; + try { + await apiClient.getEnrollmentApiKey(spaceTest1EnrollmentKey1.id); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + + it('should not allow to get an default space enrolmment key from a different space', async () => { + let err: Error | undefined; + try { + await apiClient.getEnrollmentApiKey(defaultSpaceEnrollmentKey1.id, TEST_SPACE_1); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + }); + }); + + describe('write APIs', () => { + describe('POST /enrollment_api_keys', () => { + it('should allow to create an enrollment api key for a policy in the default space', async () => { + const res = await apiClient.postEnrollmentApiKeys({ + policy_id: defaultSpacePolicy1.item.id, + }); + expect(res.item).to.have.key('id'); + }); + it('should allow to create an enrollment api key for a policy in the same space', async () => { + const res = await apiClient.postEnrollmentApiKeys( + { + policy_id: spaceTest1Policy1.item.id, + }, + TEST_SPACE_1 + ); + expect(res.item).to.have.key('id'); + }); + + it('should not allow to create an enrollment api key for a policy in a different space', async () => { + let err: Error | undefined; + try { + await apiClient.postEnrollmentApiKeys( + { + policy_id: defaultSpacePolicy1.item.id, + }, + TEST_SPACE_1 + ); + } catch (_err) { + err = _err; + } + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + + it('should not allow to create an enrollment api key for a policy from a different space in the default space', async () => { + let err: Error | undefined; + try { + await apiClient.postEnrollmentApiKeys({ + policy_id: spaceTest1Policy1.item.id, + }); + } catch (_err) { + err = _err; + } + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + }); + describe('DELETE /enrollment_api_keys', () => { + it('should not allow to delete an enrollment api key in a different space', async () => { + let err: Error | undefined; + try { + await apiClient.deleteEnrollmentApiKey(defaultSpaceEnrollmentKey1.id, TEST_SPACE_1); + } catch (_err) { + err = _err; + } + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + + it('should not allow to delete an enrollment api key from a different space in the default space', async () => { + let err: Error | undefined; + try { + await apiClient.deleteEnrollmentApiKey(spaceTest1EnrollmentKey1.id); + } catch (_err) { + err = _err; + } + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + it('should allow to delete an enrollment api key in the default space', async () => { + await apiClient.deleteEnrollmentApiKey(defaultSpaceEnrollmentKey1.id); + }); + it('should allow to create an enrollment api key in the same space', async () => { + await apiClient.deleteEnrollmentApiKey(spaceTest1EnrollmentKey1.id, TEST_SPACE_1); + }); + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/helpers.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/helpers.ts new file mode 100644 index 0000000000000..fe731e323ce12 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/helpers.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Client } from '@elastic/elasticsearch'; + +export async function cleanFleetIndices(esClient: Client) { + await Promise.all([ + esClient.deleteByQuery({ + index: '.fleet-enrollment-api-keys', + q: '*', + ignore_unavailable: true, + refresh: true, + }), + esClient.deleteByQuery({ + index: '.fleet-agents', + q: '*', + ignore_unavailable: true, + refresh: true, + }), + ]); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/index.js b/x-pack/test/fleet_api_integration/apis/space_awareness/index.js new file mode 100644 index 0000000000000..4313c329104f2 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/index.js @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export default function loadTests({ loadTestFile }) { + describe('Space awareness', () => { + loadTestFile(require.resolve('./enrollment_api_keys')); + loadTestFile(require.resolve('./uninstall_tokens')); + loadTestFile(require.resolve('./agent_policies')); + loadTestFile(require.resolve('./agents')); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/space_helpers.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/space_helpers.ts new file mode 100644 index 0000000000000..b529c6390517a --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/space_helpers.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; + +export const TEST_SPACE_1 = 'test1'; + +export function setupTestSpaces(providerContex: FtrProviderContext) { + const kibanaServer = providerContex.getService('kibanaServer'); + before(async () => + Promise.all([ + kibanaServer.spaces + .create({ + id: TEST_SPACE_1, + name: TEST_SPACE_1, + }) + .catch((err) => {}), + ]) + ); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/uninstall_tokens.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/uninstall_tokens.ts new file mode 100644 index 0000000000000..12bbc8bec3b37 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/uninstall_tokens.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { CreateAgentPolicyResponse } from '@kbn/fleet-plugin/common'; +import { UninstallTokenMetadata } from '@kbn/fleet-plugin/common/types/models/uninstall_token'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { SpaceTestApiClient } from './api_helper'; +import { cleanFleetIndices } from './helpers'; +import { setupTestSpaces, TEST_SPACE_1 } from './space_helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esClient = getService('es'); + const kibanaServer = getService('kibanaServer'); + + describe('uninstall tokens', async function () { + skipIfNoDockerRegistry(providerContext); + const apiClient = new SpaceTestApiClient(supertest); + + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + let defaultSpacePolicy1: CreateAgentPolicyResponse; + let spaceTest1Policy1: CreateAgentPolicyResponse; + let spaceTest1Policy2: CreateAgentPolicyResponse; + let defaultSpaceToken: UninstallTokenMetadata; + let spaceTest1Token: UninstallTokenMetadata; + // Create agent policies it should create am uninstall token for every keys + before(async () => { + const [_defaultSpacePolicy1, _spaceTest1Policy1, _spaceTest1Policy2] = await Promise.all([ + apiClient.createAgentPolicy(), + apiClient.createAgentPolicy(TEST_SPACE_1), + apiClient.createAgentPolicy(TEST_SPACE_1), + ]); + defaultSpacePolicy1 = _defaultSpacePolicy1; + spaceTest1Policy1 = _spaceTest1Policy1; + spaceTest1Policy2 = _spaceTest1Policy2; + + const space1Tokens = await apiClient.getUninstallTokens(TEST_SPACE_1); + const defaultSpaceTokens = await apiClient.getUninstallTokens(); + defaultSpaceToken = defaultSpaceTokens.items[0]; + spaceTest1Token = space1Tokens.items[0]; + }); + + describe('GET /uninstall_tokens', () => { + it('should return uninstall_tokens in a specific space', async () => { + const tokens = await apiClient.getUninstallTokens(TEST_SPACE_1); + expect(tokens.total).to.eql(2); + const policyIds = tokens.items?.map((item) => item.policy_id); + expect(policyIds).to.contain(spaceTest1Policy1.item.id); + expect(policyIds).to.contain(spaceTest1Policy2.item.id); + expect(policyIds).not.to.contain(defaultSpacePolicy1.item.id); + }); + + it('should return uninstall_tokens in default space', async () => { + const tokens = await apiClient.getUninstallTokens(); + expect(tokens.total).to.eql(1); + const policyIds = tokens.items?.map((item) => item.policy_id); + expect(policyIds).not.to.contain(spaceTest1Policy1.item.id); + expect(policyIds).not.contain(spaceTest1Policy2.item.id); + expect(policyIds).to.contain(defaultSpacePolicy1.item.id); + }); + }); + + describe('GET /uninstall_tokens/{id}', () => { + it('should allow to access a uninstall token in a specific space', async () => { + await apiClient.getUninstallToken(spaceTest1Token.id, TEST_SPACE_1); + }); + it('should not allow to get an uninstall token from a different space from the default space', async () => { + let err: Error | undefined; + try { + await apiClient.getUninstallToken(spaceTest1Token.id); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + + it('should not allow to get an default space uninstall token from a different space', async () => { + let err: Error | undefined; + try { + await apiClient.getUninstallToken(defaultSpaceToken.id, TEST_SPACE_1); + } catch (_err) { + err = _err; + } + + expect(err).to.be.an(Error); + expect(err?.message).to.match(/404 "Not Found"/); + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/config.space_awareness.ts b/x-pack/test/fleet_api_integration/config.space_awareness.ts new file mode 100644 index 0000000000000..f77d3826964ed --- /dev/null +++ b/x-pack/test/fleet_api_integration/config.space_awareness.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseFleetApiConfig = await readConfigFile(require.resolve('./config.base.ts')); + + const serverArgs: string[] = [...baseFleetApiConfig.get('kbnTestServer.serverArgs')]; + + const enableExperimentalIndex = serverArgs.findIndex((val) => + val.includes('xpack.fleet.enableExperimental') + ); + serverArgs[enableExperimentalIndex] = `--xpack.fleet.enableExperimental=${JSON.stringify([ + 'outputSecretsStorage', + 'agentTamperProtectionEnabled', + 'enableStrictKQLValidation', + 'subfeaturePrivileges', + 'enablePackagesStateMachine', + 'useSpaceAwareness', + ])}`; + + return { + ...baseFleetApiConfig.getAll(), + kbnTestServer: { + ...baseFleetApiConfig.get('kbnTestServer'), + serverArgs, + }, + testFiles: [require.resolve('./apis/space_awareness')], + junit: { + reportName: 'X-Pack Fleet Agent Policy API Integration Tests', + }, + }; +} From 3959af2a305bae1e17380594ddd39919fdfc4696 Mon Sep 17 00:00:00 2001 From: Katerina Date: Mon, 17 Jun 2024 17:06:01 +0300 Subject: [PATCH 009/127] [APM] Add default time field: `@timestamp` for the ad hoc data view (#186167) ## Summary unblocks https://github.com/elastic/kibana/pull/182107 --- .../apm/public/hooks/use_adhoc_apm_data_view.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/apm/public/hooks/use_adhoc_apm_data_view.ts b/x-pack/plugins/observability_solution/apm/public/hooks/use_adhoc_apm_data_view.ts index 68074b80ce206..918a701ea169f 100644 --- a/x-pack/plugins/observability_solution/apm/public/hooks/use_adhoc_apm_data_view.ts +++ b/x-pack/plugins/observability_solution/apm/public/hooks/use_adhoc_apm_data_view.ts @@ -29,7 +29,11 @@ export function useAdHocApmDataView() { try { const displayError = false; - return await services.dataViews.create({ title: indexPattern }, undefined, displayError); + return await services.dataViews.create( + { title: indexPattern, timeFieldName: '@timestamp' }, + undefined, + displayError + ); } catch (e) { const noDataScreen = e.message.includes('No matching indices found'); if (noDataScreen) { From c9bd32623a37113f74bf1485b9a6d3a202d6f543 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Mon, 17 Jun 2024 16:07:43 +0200 Subject: [PATCH 010/127] [Security Solution] Optimize Cell Actions extra render (#186282) ## Summary This PR optimizes Security Solution Cell actions so that there is no extra re-render of the complete data-grid which can be, in some cases, very expensive. Today Security Solutions Cell actions returns cell actions in 3 steps as show below. This cycle is repeated for every updated in the columns. ```mermaid flowchart TD useDataGridColumnsCellActions --> initialActions[setEmptyCellActions] --> loading{isLoading} loadingTrue[SetLoadingActions] loadingFalse[SetFinalActions] loading --> |yes|loadingTrue loading --> |no|loadingFalse finalActions[outputCellActions] initialActions --> finalActions loadingTrue --> finalActions loadingFalse --> finalActions ``` Each update to above state updates causes the entire data grid to re-render. This PR removes the `loading` state to be returned as it is not very useful for consumers. > [!CAUTION] > I have made an assumption that `Loading` state is not needed by the consumer. Feel free to correct me if that assumption is incorrect. This change make `useDataGridColumnsCellActions` return `emptyActions` initially and then the `changed actions` directly as shown below. There is not intermediate loading state on every render. ```mermaid flowchart TD useDataGridColumnsCellActions --> initialActions[setEmptyCellActions] --> loading{isLoading} loadingFalse[SetFinalActions] noop[No-op] loading --> |yes|noop loading --> |no|loadingFalse finalActions[outputCellActions] initialActions --> finalActions loadingFalse --> finalActions ``` ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- ...use_data_grid_column_cell_actions.test.tsx | 16 ++----- .../use_data_grid_column_cell_actions.tsx | 46 +++++++++---------- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx index 67860ded13bdc..f72b31a0f834d 100644 --- a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx +++ b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx @@ -10,7 +10,7 @@ import type { JSXElementConstructor, MutableRefObject } from 'react'; import React from 'react'; import type { EuiDataGridColumnCellActionProps, EuiDataGridRefProps } from '@elastic/eui'; import { EuiButtonEmpty, type EuiDataGridColumnCellAction } from '@elastic/eui'; -import { render, waitFor, act } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { makeAction } from '../mocks/helpers'; import type { UseDataGridColumnsCellActionsProps } from './use_data_grid_column_cell_actions'; @@ -74,8 +74,8 @@ describe('useDataGridColumnsCellActions', () => { const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - expect(result.current).toHaveLength(columns.length); - expect(result.current[0]).toHaveLength(1); // loader + + expect(result.current).toHaveLength(0); await waitForNextUpdate(); @@ -83,16 +83,6 @@ describe('useDataGridColumnsCellActions', () => { expect(result.current[0]).toHaveLength(actions.length); }); - it('should render cell actions loading state', async () => { - const { result } = renderHook(useDataGridColumnsCellActions, { - initialProps: useDataGridColumnsCellActionsProps, - }); - await act(async () => { - const cellAction = renderCellAction(result.current[0][0]); - expect(cellAction.getByTestId('dataGridColumnCellAction-loading')).toBeInTheDocument(); - }); - }); - it('should call getCellValue with the proper params', async () => { const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, diff --git a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx index b5b8ea32d9b52..96132a80bbeb2 100644 --- a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx +++ b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx @@ -7,9 +7,9 @@ */ import type { MutableRefObject } from 'react'; -import React, { useCallback, useMemo, useRef } from 'react'; +import React, { useCallback, useMemo, useRef, useState, useEffect } from 'react'; import type { EuiDataGridRefProps } from '@elastic/eui'; -import { EuiLoadingSpinner, type EuiDataGridColumnCellAction } from '@elastic/eui'; +import { type EuiDataGridColumnCellAction } from '@elastic/eui'; import type { FieldSpec } from '@kbn/data-views-plugin/common'; import type { CellAction, @@ -46,10 +46,6 @@ export type UseDataGridColumnsCellActions< P extends UseDataGridColumnsCellActionsProps = UseDataGridColumnsCellActionsProps > = (props: P) => EuiDataGridColumnCellAction[][]; -// static actions array references to prevent React updates -const loadingColumnActions: EuiDataGridColumnCellAction[] = [ - () => , -]; const emptyActions: EuiDataGridColumnCellAction[][] = []; export const useDataGridColumnsCellActions: UseDataGridColumnsCellActions = ({ @@ -60,6 +56,8 @@ export const useDataGridColumnsCellActions: UseDataGridColumnsCellActions = ({ dataGridRef, disabledActionTypes = [], }) => { + const [cellActions, setCellActions] = useState(emptyActions); + const bulkContexts: CellActionCompatibilityContext[] | undefined = useMemo(() => { if (!triggerId || !fields?.length) { return undefined; @@ -75,35 +73,35 @@ export const useDataGridColumnsCellActions: UseDataGridColumnsCellActions = ({ disabledActionTypes, }); - const columnsCellActions = useMemo(() => { - if (loading) { - return fields?.length ? fields.map(() => loadingColumnActions) : emptyActions; - } - if (!triggerId || !columnsActions?.length || !fields?.length) { - return emptyActions; + useEffect(() => { + // no-op + if (loading || !triggerId || !columnsActions?.length || !fields?.length) { + return; } // Check for a temporary inconsistency because `useBulkLoadActions` takes one render loop before setting `loading` to true. // It will eventually update to a consistent state if (columnsActions.length !== fields.length) { - return emptyActions; + return; } - return columnsActions.map((actions, columnIndex) => - actions.map((action) => - createColumnCellAction({ - action, - field: fields[columnIndex], - getCellValue, - metadata, - triggerId, - dataGridRef, - }) + setCellActions( + columnsActions.map((actions, columnIndex) => + actions.map((action) => + createColumnCellAction({ + action, + field: fields[columnIndex], + getCellValue, + metadata, + triggerId, + dataGridRef, + }) + ) ) ); }, [columnsActions, fields, getCellValue, loading, metadata, triggerId, dataGridRef]); - return columnsCellActions; + return cellActions; }; interface CreateColumnCellActionParams From 089c61efb06ba7090f126df8e579284a06f0d68f Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Mon, 17 Jun 2024 16:11:48 +0200 Subject: [PATCH 011/127] [Security Solution] Unified Timeline - Fix Flaky tests (#184747) ## Summary fixes flaky tests and below issues : - https://github.com/elastic/kibana/issues/179831 - https://github.com/elastic/kibana/issues/179843 - https://github.com/elastic/kibana/issues/180956 - https://github.com/elastic/kibana/issues/180937 - https://github.com/elastic/security-team/issues/9549 - https://github.com/elastic/security-team/issues/9548 --- .../src/utils/get_render_cell_popover.tsx | 10 +- .../src/utils/get_render_cell_value.tsx | 9 +- .../components/header_actions/actions.tsx | 14 +- .../header_actions/header_actions.tsx | 13 +- .../timeline_actions/alert_context_menu.tsx | 3 +- .../body/events/event_column_view.test.tsx | 6 +- .../body/unified_timeline_body.test.tsx | 2 + .../components/timeline/tabs/eql/index.tsx | 10 +- .../components/timeline/tabs/pinned/index.tsx | 8 +- .../components/timeline/tabs/query/index.tsx | 8 +- .../query_tab_unified_components.test.tsx | 214 ++++++++++++------ ...use_timeline_control_columns.test.tsx.snap | 6 +- .../use_timeline_control_columns.test.tsx | 52 ++++- .../shared/use_timeline_control_columns.tsx | 59 ++++- .../timelines/components/timeline/types.ts | 18 ++ .../data_table/control_column_cell_render.tsx | 14 +- .../data_table/index.test.tsx | 106 +++------ .../unified_components/index.test.tsx | 26 ++- .../timeline/unified_components/index.tsx | 11 +- .../timelines/table_row_actions.cy.ts | 48 ++++ .../table_row_actions.cy.ts | 57 +++++ .../cypress/tasks/timeline.ts | 22 ++ 22 files changed, 492 insertions(+), 224 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/timelines/components/timeline/types.ts create mode 100644 x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/table_row_actions.cy.ts create mode 100644 x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/unified_components/table_row_actions.cy.ts diff --git a/packages/kbn-unified-data-table/src/utils/get_render_cell_popover.tsx b/packages/kbn-unified-data-table/src/utils/get_render_cell_popover.tsx index ea6e2a54a90de..7d8d8335cffff 100644 --- a/packages/kbn-unified-data-table/src/utils/get_render_cell_popover.tsx +++ b/packages/kbn-unified-data-table/src/utils/get_render_cell_popover.tsx @@ -19,7 +19,9 @@ import React, { memo, useEffect } from 'react'; * * */ export const getCustomCellPopoverRenderer = () => { - return memo(function RenderCustomCellPopover(props: EuiDataGridCellPopoverElementProps) { + const RenderCustomCellPopoverMemoized = memo(function RenderCustomCellPopoverMemoized( + props: EuiDataGridCellPopoverElementProps + ) { const { setCellPopoverProps, DefaultCellPopover } = props; useEffect(() => { @@ -30,4 +32,10 @@ export const getCustomCellPopoverRenderer = () => { return ; }); + + // Components passed to EUI DataGrid cannot be memoized components + // otherwise EUI throws an error `typeof Component !== 'function'` + return (props: EuiDataGridCellPopoverElementProps) => ( + + ); }; diff --git a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.tsx b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.tsx index a56336fd53de7..35234bdb58d8f 100644 --- a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.tsx +++ b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { memo, useEffect, useContext } from 'react'; +import React, { useEffect, useContext } from 'react'; import { i18n } from '@kbn/i18n'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { @@ -47,10 +47,7 @@ export const getRenderCellValueFn = ({ externalCustomRenderers?: CustomCellRenderer; isPlainRecord?: boolean; }) => { - /** - * memo is imperative here otherwise the cell will re-render on every hover on every cell - */ - return memo(function UnifiedDataTableRenderCellValue({ + return function UnifiedDataTableRenderCellValue({ rowIndex, columnId, isDetails, @@ -149,7 +146,7 @@ export const getRenderCellValueFn = ({ }} /> ); - }); + }; }; /** diff --git a/x-pack/plugins/security_solution/public/common/components/header_actions/actions.tsx b/x-pack/plugins/security_solution/public/common/components/header_actions/actions.tsx index 6efaaa5d01ccd..16fabb97fb464 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_actions/actions.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_actions/actions.tsx @@ -11,6 +11,7 @@ import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import styled from 'styled-components'; import { TimelineTabs, TableId } from '@kbn/securitysolution-data-table'; +import { selectTimelineById } from '../../../timelines/store/selectors'; import { eventHasNotes, getEventType, @@ -18,7 +19,7 @@ import { } from '../../../timelines/components/timeline/body/helpers'; import { getScopedActions, isTimelineScope } from '../../../helpers'; import { useIsInvestigateInResolverActionEnabled } from '../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver'; -import { timelineActions, timelineSelectors } from '../../../timelines/store'; +import { timelineActions } from '../../../timelines/store'; import type { ActionProps, OnPinEvent } from '../../../../common/types'; import { TimelineId } from '../../../../common/types'; import { AddEventNoteAction } from './add_note_icon_item'; @@ -66,11 +67,10 @@ const ActionsComponent: React.FC = ({ 'unifiedComponentsInTimelineEnabled' ); const emptyNotes: string[] = []; - const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []); - const timelineType = useShallowEqualSelector( - (state) => - (isTimelineScope(timelineId) ? getTimeline(state, timelineId) : timelineDefaults).timelineType + const { timelineType } = useShallowEqualSelector((state) => + isTimelineScope(timelineId) ? selectTimelineById(state, timelineId) : timelineDefaults ); + const { startTransaction } = useStartTransaction(); const isEnterprisePlus = useLicense().isEnterprise(); @@ -213,8 +213,8 @@ const ActionsComponent: React.FC = ({ onEventDetailsPanelOpened(); }, [activeStep, incrementStep, isTourAnchor, isTourShown, onEventDetailsPanelOpened]); const showExpandEvent = useMemo( - () => !unifiedComponentsInTimelineEnabled || isEventViewer || timelineId !== TimelineId.active, - [isEventViewer, timelineId, unifiedComponentsInTimelineEnabled] + () => !unifiedComponentsInTimelineEnabled || isEventViewer, + [isEventViewer, unifiedComponentsInTimelineEnabled] ); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/header_actions/header_actions.tsx b/x-pack/plugins/security_solution/public/common/components/header_actions/header_actions.tsx index d65b6035eaeea..7b60434d5c288 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_actions/header_actions.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_actions/header_actions.tsx @@ -16,8 +16,7 @@ import { TimelineTabs, TimelineId } from '../../../../common/types'; import { isFullScreen } from '../../../timelines/components/timeline/body/column_headers'; import { isActiveTimeline } from '../../../helpers'; import { getColumnHeader } from '../../../timelines/components/timeline/body/column_headers/helpers'; -import { timelineActions, timelineSelectors } from '../../../timelines/store'; -import { useDeepEqualSelector } from '../../hooks/use_selector'; +import { timelineActions } from '../../../timelines/store'; import { useGlobalFullScreen, useTimelineFullScreen } from '../../containers/use_full_screen'; import { useKibana } from '../../lib/kibana'; import { DEFAULT_ACTION_BUTTON_WIDTH } from '.'; @@ -27,6 +26,8 @@ import { EXIT_FULL_SCREEN } from '../exit_full_screen/translations'; import { EventsSelect } from '../../../timelines/components/timeline/body/column_headers/events_select'; import * as i18n from './translations'; import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; +import { useDeepEqualSelector } from '../../hooks/use_selector'; +import { selectTimelineById } from '../../../timelines/store/selectors'; const SortingColumnsContainer = styled.div` button { @@ -90,14 +91,14 @@ const HeaderActionsComponent: React.FC = memo( const { timelineFullScreen, setTimelineFullScreen } = useTimelineFullScreen(); const dispatch = useDispatch(); - const getManageTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []); - const { defaultColumns } = useDeepEqualSelector((state) => - getManageTimeline(state, timelineId) - ); const unifiedComponentsInTimelineEnabled = useIsExperimentalFeatureEnabled( 'unifiedComponentsInTimelineEnabled' ); + const { defaultColumns } = useDeepEqualSelector((state) => + selectTimelineById(state, timelineId) + ); + const toggleFullScreen = useCallback(() => { if (timelineId === TimelineId.active) { setTimelineFullScreen(!timelineFullScreen); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index 0143b584ea8c5..d18a4c5bf658c 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -152,8 +152,9 @@ const AlertContextMenuComponent: React.FC = ({ refetchQuery([timelineQuery]); } else { refetchQuery(globalQuery); - if (refetch) refetch(); } + + if (refetch) refetch(); }, [scopeId, globalQuery, timelineQuery, refetch]); const ruleIndex = diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx index 9d4264dd5b079..34578db7e5a15 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx @@ -145,14 +145,16 @@ describe('EventColumnView', () => { }); test('it renders correct tooltip for NotesButton - timeline template', () => { - (useShallowEqualSelector as jest.Mock).mockReturnValue(TimelineType.template); + (useShallowEqualSelector as jest.Mock).mockReturnValue({ + timelineType: TimelineType.template, + }); const wrapper = mount(, { wrappingComponent: TestProviders }); expect(wrapper.find('[data-test-subj="add-note"]').prop('toolTip')).toEqual( NOTES_DISABLE_TOOLTIP ); - (useShallowEqualSelector as jest.Mock).mockReturnValue(TimelineType.default); + (useShallowEqualSelector as jest.Mock).mockReturnValue({ timelineType: TimelineType.default }); }); test('it does NOT render a pin button when isEventViewer is true', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/unified_timeline_body.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/unified_timeline_body.test.tsx index 401fe8763ada5..21a923653237a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/unified_timeline_body.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/unified_timeline_body.test.tsx @@ -46,6 +46,8 @@ const defaultProps: UnifiedTimelineBodyProps = { activePage: 0, querySize: 0, }, + eventIdToNoteIds: {} as Record, + pinnedEventIds: {} as Record, }; const renderTestComponents = (props?: UnifiedTimelineBodyProps) => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx index 99952f170f13c..b9c8fd9edada5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx @@ -92,8 +92,6 @@ export const EqlTabContentComponent: React.FC = ({ } = useSourcererDataView(SourcererScopeName.timeline); const { augmentedColumnHeaders, timelineQueryFieldsFromColumns } = useTimelineColumns(columns); - const leadingControlColumns = useTimelineControlColumn(columns, TIMELINE_NO_SORTING); - const unifiedComponentsInTimelineEnabled = useIsExperimentalFeatureEnabled( 'unifiedComponentsInTimelineEnabled' ); @@ -137,6 +135,14 @@ export const EqlTabContentComponent: React.FC = ({ timerangeKind, }); + const leadingControlColumns = useTimelineControlColumn({ + columns, + sort: TIMELINE_NO_SORTING, + timelineId, + activeTab: TimelineTabs.eql, + refetch, + }); + const isQueryLoading = useMemo( () => dataLoadingState === DataLoadingState.loading || diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx index 7a4242178f027..27074cceb45b1 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx @@ -171,7 +171,13 @@ export const PinnedTabContentComponent: React.FC = ({ timerangeKind: undefined, }); - const leadingControlColumns = useTimelineControlColumn(columns, sort); + const leadingControlColumns = useTimelineControlColumn({ + columns, + sort, + timelineId, + activeTab: TimelineTabs.pinned, + refetch, + }); const isQueryLoading = useMemo( () => [DataLoadingState.loading, DataLoadingState.loadingMore].includes(queryLoadingState), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx index 21165080d3957..745cd04daaee5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx @@ -203,7 +203,13 @@ export const QueryTabContentComponent: React.FC = ({ timerangeKind, }); - const leadingControlColumns = useTimelineControlColumn(columns, sort); + const leadingControlColumns = useTimelineControlColumn({ + columns, + sort, + timelineId, + activeTab: TimelineTabs.query, + refetch, + }); useEffect(() => { dispatch( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx index 36284be9dad18..0a8fdcbaacd87 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { ComponentProps } from 'react'; +import type { ComponentProps, FunctionComponent } from 'react'; import React, { useEffect } from 'react'; import QueryTabContent from '.'; import { defaultRowRenderers } from '../../body/renderers'; @@ -15,7 +15,9 @@ import { useTimelineEventsDetails } from '../../../../containers/details'; import { useSourcererDataView } from '../../../../../sourcerer/containers'; import { mockSourcererScope } from '../../../../../sourcerer/containers/mocks'; import { + createMockStore, createSecuritySolutionStorageMock, + mockGlobalState, mockTimelineData, TestProviders, } from '../../../../../common/mock'; @@ -29,7 +31,13 @@ import { timelineActions } from '../../../../store'; import type { ExperimentalFeatures } from '../../../../../../common'; import { allowedExperimentalValues } from '../../../../../../common'; import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { cloneDeep, flatten } from 'lodash'; +import { defaultUdtHeaders } from '../../unified_components/default_headers'; +import { defaultColumnHeaderType } from '../../body/column_headers/default_headers'; +import { useUserPrivileges } from '../../../../../common/components/user_privileges'; +import { getEndpointPrivilegesInitialStateMock } from '../../../../../common/components/user_privileges/endpoint/mocks'; +import userEvent from '@testing-library/user-event'; + +jest.mock('../../../../../common/components/user_privileges'); jest.mock('../../../../containers', () => ({ useTimelineEvents: jest.fn(), @@ -54,9 +62,17 @@ jest.mock('../../../../../common/lib/kuery'); jest.mock('../../../../../common/hooks/use_experimental_features'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: jest.fn(() => ({ + pathname: '', + search: '', + })), +})); + // These tests can take more than standard timeout of 5s -// that is why we are setting it to 15s -const SPECIAL_TEST_TIMEOUT = 15000; +// that is why we are increasing it. +const SPECIAL_TEST_TIMEOUT = 50000; const useIsExperimentalFeatureEnabledMock = jest.fn((feature: keyof ExperimentalFeatures) => { if (feature === 'unifiedComponentsInTimelineEnabled') { @@ -67,7 +83,7 @@ const useIsExperimentalFeatureEnabledMock = jest.fn((feature: keyof Experimental jest.mock('../../../../../common/lib/kibana'); -// unified-field-list is is reporiting multiple analytics events +// unified-field-list is reporting multiple analytics events jest.mock(`@kbn/analytics-client`); const TestComponent = (props: Partial>) => { @@ -98,44 +114,41 @@ const TestComponent = (props: Partial>) = return ; }; +const customColumnOrder = [ + ...defaultUdtHeaders, + { + columnHeaderType: defaultColumnHeaderType, + id: 'event.severity', + }, +]; + +const mockState = { + ...structuredClone(mockGlobalState), +}; + +mockState.timeline.timelineById[TimelineId.test].columns = customColumnOrder; + +const TestWrapper: FunctionComponent = ({ children }) => { + return {children}; +}; + const renderTestComponents = (props?: Partial>) => { return render(, { - wrapper: TestProviders, + wrapper: TestWrapper, }); }; -const changeItemsPerPageTo = (newItemsPerPage: number) => { - fireEvent.click(screen.getByTestId('tablePaginationPopoverButton')); - fireEvent.click(screen.getByTestId(`tablePagination-${newItemsPerPage}-rows`)); - expect(screen.getByTestId('tablePaginationPopoverButton')).toHaveTextContent( - `Rows per page: ${newItemsPerPage}` - ); -}; - const loadPageMock = jest.fn(); -const useTimelineEventsMock = jest.fn(() => [ - false, - { - events: cloneDeep(mockTimelineData), - pageInfo: { - activePage: 0, - totalPages: 10, - }, - refreshedAt: Date.now(), - totalCount: 70, - loadPage: loadPageMock, - }, -]); - const useSourcererDataViewMocked = jest.fn().mockReturnValue({ ...mockSourcererScope, }); const { storage: storageMock } = createSecuritySolutionStorageMock(); -// Flaky : See https://github.com/elastic/kibana/issues/179831 -describe.skip('query tab with unified timeline', () => { +let useTimelineEventsMock = jest.fn(); + +describe('query tab with unified timeline', () => { const kibanaServiceMock: StartServices = { ...createStartServicesMock(), storage: storageMock, @@ -149,9 +162,20 @@ describe.skip('query tab with unified timeline', () => { }); beforeEach(() => { - // increase timeout for these tests as they are rendering a complete table with ~30 rows which can take time. - const ONE_SECOND = 1000; - jest.setTimeout(10 * ONE_SECOND); + useTimelineEventsMock = jest.fn(() => [ + false, + { + events: structuredClone(mockTimelineData.slice(0, 1)), + pageInfo: { + activePage: 0, + totalPages: 3, + }, + refreshedAt: Date.now(), + totalCount: 3, + loadPage: loadPageMock, + }, + ]); + HTMLElement.prototype.getBoundingClientRect = jest.fn(() => { return { width: 1000, @@ -176,6 +200,12 @@ describe.skip('query tab with unified timeline', () => { (useIsExperimentalFeatureEnabled as jest.Mock).mockImplementation( useIsExperimentalFeatureEnabledMock ); + + (useUserPrivileges as jest.Mock).mockReturnValue({ + kibanaSecuritySolutionsPrivileges: { crud: true, read: true }, + endpointPrivileges: getEndpointPrivilegesInitialStateMock(), + detectionEnginePrivileges: { loading: false, error: undefined, result: undefined }, + }); }); describe('render', () => { @@ -235,15 +265,39 @@ describe.skip('query tab with unified timeline', () => { fireEvent.click(screen.getByLabelText('Closes this modal window')); - expect(screen.queryByTestId('row-renderers-modal')).toBeFalsy(); + expect(screen.queryByTestId('row-renderers-modal')).not.toBeInTheDocument(); - expect(screen.queryByTestId('timeline-row-renderer-0')).toBeFalsy(); + expect(screen.queryByTestId('timeline-row-renderer-0')).not.toBeInTheDocument(); }, SPECIAL_TEST_TIMEOUT ); }); describe('pagination', () => { + beforeEach(() => { + // should return all the records instead just 3 + // as the case in the default mock + useTimelineEventsMock = jest.fn(() => [ + false, + { + events: structuredClone(mockTimelineData), + pageInfo: { + activePage: 0, + totalPages: 10, + }, + refreshedAt: Date.now(), + totalCount: 70, + loadPage: loadPageMock, + }, + ]); + + (useTimelineEvents as jest.Mock).mockImplementation(useTimelineEventsMock); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + it( 'should paginate correctly', async () => { @@ -296,9 +350,14 @@ describe.skip('query tab with unified timeline', () => { await waitFor(() => { expect(screen.getByTestId('discoverDocTable')).toBeVisible(); }); + + const messageColumnIndex = + customColumnOrder.findIndex((header) => header.id === 'message') + 3; + // 3 is the offset for additional leading columns on left + expect(container.querySelector('[data-gridcell-column-id="message"]')).toHaveAttribute( 'data-gridcell-column-index', - '12' + String(messageColumnIndex) ); expect(container.querySelector('[data-gridcell-column-id="message"]')).toBeInTheDocument(); @@ -318,7 +377,7 @@ describe.skip('query tab with unified timeline', () => { await waitFor(() => { expect(container.querySelector('[data-gridcell-column-id="message"]')).toHaveAttribute( 'data-gridcell-column-index', - '11' + String(messageColumnIndex - 1) ); }); }, @@ -391,7 +450,7 @@ describe.skip('query tab with unified timeline', () => { sort: [ { direction: 'asc', - esTypes: [], + esTypes: ['date'], field: '@timestamp', type: 'date', }, @@ -439,7 +498,7 @@ describe.skip('query tab with unified timeline', () => { sort: [ { direction: 'desc', - esTypes: [], + esTypes: ['date'], field: '@timestamp', type: 'date', }, @@ -498,7 +557,7 @@ describe.skip('query tab with unified timeline', () => { sort: [ { direction: 'desc', - esTypes: [], + esTypes: ['date'], field: '@timestamp', type: 'date', }, @@ -547,7 +606,6 @@ describe.skip('query tab with unified timeline', () => { SPECIAL_TEST_TIMEOUT ); - // Failing: See https://github.com/elastic/kibana/issues/179831 it( 'should be able to sort by multiple columns', async () => { @@ -608,7 +666,7 @@ describe.skip('query tab with unified timeline', () => { await waitFor(() => { expect(screen.getByTestId('fieldListGroupedSelectedFields-count')).toHaveTextContent( - '11' + String(customColumnOrder.length) ); }); @@ -620,7 +678,7 @@ describe.skip('query tab with unified timeline', () => { // column not longer exists in the table await waitFor(() => { expect(screen.getByTestId('fieldListGroupedSelectedFields-count')).toHaveTextContent( - '10' + String(customColumnOrder.length - 1) ); }); expect(screen.queryAllByTestId(`dataGridHeaderCell-${field.name}`)).toHaveLength(0); @@ -640,7 +698,7 @@ describe.skip('query tab with unified timeline', () => { await waitFor(() => { expect(screen.getByTestId('fieldListGroupedSelectedFields-count')).toHaveTextContent( - '11' + String(customColumnOrder.length) ); }); @@ -653,7 +711,7 @@ describe.skip('query tab with unified timeline', () => { await waitFor(() => { expect(screen.getByTestId('fieldListGroupedSelectedFields-count')).toHaveTextContent( - '12' + String(customColumnOrder.length + 1) ); }); expect(screen.queryAllByTestId(`dataGridHeaderCell-${field.name}`)).toHaveLength(1); @@ -693,50 +751,64 @@ describe.skip('query tab with unified timeline', () => { async () => { renderTestComponents(); expect(await screen.findByTestId('timeline-sidebar')).toBeVisible(); - await waitFor(() => { - expect(screen.getByTestId('fieldListGroupedAvailableFields-count')).toHaveTextContent( - '37' - ); - }); + + expect(screen.getByTestId('fieldListGroupedFieldGroups')).toBeVisible(); fireEvent.click(screen.getByTitle('Hide sidebar')); await waitFor(() => { - expect(screen.queryAllByTestId('fieldListGroupedAvailableFields-count')).toHaveLength(0); + expect(screen.queryByTestId('fieldListGroupedFieldGroups')).not.toBeInTheDocument(); }); }, SPECIAL_TEST_TIMEOUT ); + }); + describe('row leading actions', () => { it( - 'should have all populated fields in Available fields section', + 'should be able to add notes', async () => { - const listOfPopulatedFields = new Set( - flatten( - mockTimelineData.map((dataItem) => - dataItem.data.map((item) => - item.value && item.value.length > 0 ? item.field : undefined - ) - ) - ).filter((item) => typeof item !== 'undefined') - ); - renderTestComponents(); + expect(await screen.findByTestId('discoverDocTable')).toBeVisible(); - expect(await screen.findByTestId('timeline-sidebar')).toBeVisible(); + await waitFor(() => { + expect(screen.getByTestId('timeline-notes-button-small')).not.toBeDisabled(); + }); + + fireEvent.click(screen.getByTestId('timeline-notes-button-small')); + + await waitFor(() => { + expect(screen.getByTestId('add-note-container')).toBeVisible(); + }); + }, + SPECIAL_TEST_TIMEOUT + ); + + it( + 'should be cancel adding notes', + async () => { + renderTestComponents(); expect(await screen.findByTestId('discoverDocTable')).toBeVisible(); - changeItemsPerPageTo(100); + await waitFor(() => { + expect(screen.getByTestId('timeline-notes-button-small')).not.toBeDisabled(); + }); - const availableFields = screen.getByTestId('fieldListGroupedAvailableFields'); + fireEvent.click(screen.getByTestId('timeline-notes-button-small')); + + await waitFor(() => { + expect(screen.getByTestId('add-note-container')).toBeVisible(); + }); - for (const field of listOfPopulatedFields) { - fireEvent.change(screen.getByTestId('fieldListFiltersFieldSearch'), { - target: { value: field }, - }); + userEvent.type(screen.getByTestId('euiMarkdownEditorTextArea'), 'Test Note 1'); - expect(within(availableFields).getByTestId(`field-${field}`)); - } + expect(screen.getByTestId('cancel')).not.toBeDisabled(); + + fireEvent.click(screen.getByTestId('cancel')); + + await waitFor(() => { + expect(screen.queryByTestId('add-note-container')).not.toBeInTheDocument(); + }); }, SPECIAL_TEST_TIMEOUT ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/__snapshots__/use_timeline_control_columns.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/__snapshots__/use_timeline_control_columns.test.tsx.snap index a85af556d5f4c..e96dd27082bd0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/__snapshots__/use_timeline_control_columns.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/__snapshots__/use_timeline_control_columns.test.tsx.snap @@ -5,11 +5,7 @@ Array [ Object { "headerCellRender": [Function], "id": "default-timeline-control-column", - "rowCellRender": Object { - "$$typeof": Symbol(react.memo), - "compare": null, - "type": [Function], - }, + "rowCellRender": [Function], "width": 152, }, ] diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx index b2958cb0339cb..7befceacb5449 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.test.tsx @@ -10,6 +10,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { useLicense } from '../../../../../common/hooks/use_license'; import { useTimelineControlColumn } from './use_timeline_control_columns'; import type { ColumnHeaderOptions } from '../../../../../../common/types/timeline/columns'; +import { TimelineId } from '@kbn/timelines-plugin/public/store/timeline'; +import { TimelineTabs } from '../../../../../../common/types'; jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ useIsExperimentalFeatureEnabled: jest.fn().mockReturnValue(true), @@ -37,20 +39,42 @@ describe('useTimelineColumns', () => { }, ]; + const refetchMock = jest.fn(); + describe('leadingControlColumns', () => { it('should return the leading control columns', () => { - const { result } = renderHook(() => useTimelineControlColumn(mockColumns, []), { - wrapper: TestProviders, - }); + const { result } = renderHook( + () => + useTimelineControlColumn({ + columns: mockColumns, + sort: [], + timelineId: TimelineId.test, + activeTab: TimelineTabs.query, + refetch: refetchMock, + }), + { + wrapper: TestProviders, + } + ); expect(result.current).toMatchSnapshot(); }); it('should have a width of 124 for 5 actions', () => { useLicenseMock.mockReturnValue({ isEnterprise: () => false, }); - const { result } = renderHook(() => useTimelineControlColumn(mockColumns, []), { - wrapper: TestProviders, - }); + const { result } = renderHook( + () => + useTimelineControlColumn({ + columns: mockColumns, + sort: [], + timelineId: TimelineId.test, + activeTab: TimelineTabs.query, + refetch: refetchMock, + }), + { + wrapper: TestProviders, + } + ); const controlColumn = result.current[0] as EuiDataGridControlColumn; expect(controlColumn.width).toBe(124); }); @@ -58,9 +82,19 @@ describe('useTimelineColumns', () => { useLicenseMock.mockReturnValue({ isEnterprise: () => true, }); - const { result } = renderHook(() => useTimelineControlColumn(mockColumns, []), { - wrapper: TestProviders, - }); + const { result } = renderHook( + () => + useTimelineControlColumn({ + columns: mockColumns, + sort: [], + timelineId: TimelineId.test, + activeTab: TimelineTabs.query, + refetch: refetchMock, + }), + { + wrapper: TestProviders, + } + ); const controlColumn = result.current[0] as EuiDataGridControlColumn; expect(controlColumn.width).toBe(152); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx index 736afdbbec916..02791d85de022 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/use_timeline_control_columns.tsx @@ -6,7 +6,7 @@ */ import React, { useMemo } from 'react'; -import type { EuiDataGridControlColumn } from '@elastic/eui'; +import type { EuiDataGridCellValueElementProps } from '@elastic/eui'; import type { SortColumnTable } from '@kbn/securitysolution-data-table'; import { useLicense } from '../../../../../common/hooks/use_license'; import { SourcererScopeName } from '../../../../../sourcerer/store/model'; @@ -14,17 +14,32 @@ import { useSourcererDataView } from '../../../../../sourcerer/containers'; import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import { getDefaultControlColumn } from '../../body/control_columns'; import type { UnifiedActionProps } from '../../unified_components/data_table/control_column_cell_render'; -import { TimelineId, TimelineTabs } from '../../../../../../common/types/timeline'; +import type { TimelineTabs } from '../../../../../../common/types/timeline'; import { HeaderActions } from '../../../../../common/components/header_actions/header_actions'; import { ControlColumnCellRender } from '../../unified_components/data_table/control_column_cell_render'; import type { ColumnHeaderOptions } from '../../../../../../common/types'; import { useTimelineColumns } from './use_timeline_columns'; +import type { TimelineDataGridCellContext } from '../../types'; +interface UseTimelineControlColumnArgs { + columns: ColumnHeaderOptions[]; + sort: SortColumnTable[]; + timelineId: string; + activeTab: TimelineTabs; + refetch: () => void; +} + +const EMPTY_STRING_ARRAY: string[] = []; + +const noOp = () => {}; const noSelectAll = ({ isSelected }: { isSelected: boolean }) => {}; -export const useTimelineControlColumn = ( - columns: ColumnHeaderOptions[], - sort: SortColumnTable[] -) => { +export const useTimelineControlColumn = ({ + columns, + sort, + timelineId, + activeTab, + refetch, +}: UseTimelineControlColumnArgs) => { const { browserFields } = useSourcererDataView(SourcererScopeName.timeline); const unifiedComponentsInTimelineEnabled = useIsExperimentalFeatureEnabled( @@ -55,14 +70,35 @@ export const useTimelineControlColumn = ( showSelectAllCheckbox={false} showFullScreenToggle={false} sort={sort} - tabType={TimelineTabs.pinned} + tabType={activeTab} + {...props} + timelineId={timelineId} + /> + ); + }, + rowCellRender: (props: EuiDataGridCellValueElementProps & TimelineDataGridCellContext) => { + return ( + ); }, - rowCellRender: ControlColumnCellRender, - })) as unknown as EuiDataGridControlColumn[]; + })); } else { return getDefaultControlColumn(ACTION_BUTTON_COUNT).map((x) => ({ ...x, @@ -76,5 +112,8 @@ export const useTimelineControlColumn = ( localColumns, sort, unifiedComponentsInTimelineEnabled, + timelineId, + activeTab, + refetch, ]); }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/types.ts b/x-pack/plugins/security_solution/public/timelines/components/timeline/types.ts new file mode 100644 index 0000000000000..e7dedcfa9aad3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { TimelineItem } from '@kbn/timelines-plugin/common'; +import type { TimelineModel } from '../../store/model'; + +export interface TimelineDataGridCellContext { + events: TimelineItem[]; + pinnedEventIds: TimelineModel['pinnedEventIds']; + eventIdsAddingNotes: Set; + onToggleShowNotes: (eventId?: string) => void; + eventIdToNoteIds: Record; + refetch: () => void; +} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx index 48b8eaa4fc74f..c662a06cb0dc1 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/control_column_cell_render.tsx @@ -9,7 +9,6 @@ import React, { memo, useMemo } from 'react'; import type { TimelineItem } from '@kbn/timelines-plugin/common'; import { eventIsPinned } from '../../body/helpers'; import { Actions } from '../../../../../common/components/header_actions'; -import { TimelineId } from '../../../../../../common/types'; import type { TimelineModel } from '../../../../store/model'; import type { ActionProps } from '../../../../../../common/types'; @@ -20,8 +19,12 @@ export interface UnifiedActionProps extends ActionProps { pinnedEventIds: TimelineModel['pinnedEventIds']; } -export const ControlColumnCellRender = memo(function RowCellRender(props: UnifiedActionProps) { - const { rowIndex, events, ecsData, pinnedEventIds, onToggleShowNotes, eventIdToNoteIds } = props; +export const ControlColumnCellRender = memo(function ControlColumnCellRender( + props: UnifiedActionProps +) { + const { rowIndex, events, pinnedEventIds, onToggleShowNotes, eventIdToNoteIds, timelineId } = + props; + const event = useMemo(() => events && events[rowIndex], [events, rowIndex]); const isPinned = useMemo( () => eventIsPinned({ eventId: event?._id, pinnedEventIds }), @@ -32,17 +35,14 @@ export const ControlColumnCellRender = memo(function RowCellRender(props: Unifie {...props} ariaRowindex={rowIndex} columnValues="columnValues" - ecsData={ecsData ?? event.ecs} - eventId={event?._id} eventIdToNoteIds={eventIdToNoteIds} isEventPinned={isPinned} isEventViewer={false} onEventDetailsPanelOpened={noOp} onRuleChange={noOp} showNotes={true} - timelineId={TimelineId.active} + timelineId={timelineId} toggleShowNotes={onToggleShowNotes} - refetch={noOp} rowIndex={rowIndex} /> ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.test.tsx index a03c95341a07b..52cc643cbf2e4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.test.tsx @@ -17,15 +17,29 @@ import type { ComponentProps } from 'react'; import { getColumnHeaders } from '../../body/column_headers/helpers'; import { mockSourcererScope } from '../../../../../sourcerer/containers/mocks'; import { timelineActions } from '../../../../store'; -import type { ExpandedDetailTimeline } from '../../../../../../common/types'; +import { useUnifiedTableExpandableFlyout } from '../hooks/use_unified_timeline_expandable_flyout'; jest.mock('../../../../../sourcerer/containers'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: jest.fn(() => ({ + pathname: '', + search: '', + })), +})); + const onFieldEditedMock = jest.fn(); const refetchMock = jest.fn(); const onEventClosedMock = jest.fn(); const onChangePageMock = jest.fn(); +const openFlyoutMock = jest.fn(); +const closeFlyoutMock = jest.fn(); +const isExpandableFlyoutDisabled = false; + +jest.mock('../hooks/use_unified_timeline_expandable_flyout'); + const initialEnrichedColumns = getColumnHeaders( defaultUdtHeaders, mockSourcererScope.browserFields @@ -39,7 +53,7 @@ type TestComponentProps = Partial> & { // These tests can take more than standard timeout of 5s // that is why we are setting it to 10s -const SPECIAL_TEST_TIMEOUT = 10000; +const SPECIAL_TEST_TIMEOUT = 50000; const TestComponent = (props: TestComponentProps) => { const { store = createMockStore(), ...restProps } = props; @@ -81,10 +95,17 @@ const getTimelineFromStore = ( return store.getState().timeline.timelineById[timelineId]; }; -// FLAKY: https://github.com/elastic/kibana/issues/179843 -describe.skip('unified data table', () => { +describe('unified data table', () => { beforeEach(() => { (useSourcererDataView as jest.Mock).mockReturnValue(mockSourcererScope); + (useUnifiedTableExpandableFlyout as jest.Mock).mockReturnValue({ + isExpandableFlyoutDisabled, + openFlyout: openFlyoutMock, + closeFlyout: closeFlyoutMock, + }); + }); + afterEach(() => { + jest.clearAllMocks(); }); it( @@ -269,86 +290,11 @@ describe.skip('unified data table', () => { fireEvent.click(screen.getAllByTestId('docTableExpandToggleColumn')[0]); await waitFor(() => { - expect(screen.getByTestId('timeline:details-panel:flyout')).toBeVisible(); + expect(openFlyoutMock).toHaveBeenCalledTimes(1); }); }, SPECIAL_TEST_TIMEOUT ); - - it( - 'should show details flyout when expandedDetails state is set', - async () => { - const customMockStore = createMockStore(); - const mockExpandedDetail: ExpandedDetailTimeline = { - query: { - params: { - eventId: 'some_id', - indexName: 'security-*', - }, - panelView: 'eventDetail', - }, - }; - customMockStore.dispatch( - timelineActions.toggleDetailPanel({ - id: TimelineId.test, - tabType: TimelineTabs.query, - ...mockExpandedDetail.query, - }) - ); - - render( - - ); - - await waitFor(() => { - expect(screen.getByTestId('timeline:details-panel:flyout')).toBeVisible(); - }); - }, - SPECIAL_TEST_TIMEOUT - ); - it( - 'should close details flyout when close icon is clicked', - async () => { - const customMockStore = createMockStore(); - const mockExpandedDetail: ExpandedDetailTimeline = { - query: { - params: { - eventId: 'some_id', - indexName: 'security-*', - }, - panelView: 'eventDetail', - }, - }; - - customMockStore.dispatch( - timelineActions.toggleDetailPanel({ - id: TimelineId.test, - tabType: TimelineTabs.query, - ...mockExpandedDetail.query, - }) - ); - - render( - - ); - - await waitFor(() => { - expect(screen.getByTestId('euiFlyoutCloseButton')).toBeVisible(); - }); - - fireEvent.click(screen.getByTestId('euiFlyoutCloseButton')); - expect(onEventClosedMock).toHaveBeenCalledTimes(1); - }, - SPECIAL_TEST_TIMEOUT - ); }); describe('pagination', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx index f425c72880521..bca35ae0af446 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx @@ -58,6 +58,14 @@ jest.mock('../../../../common/lib/kuery'); jest.mock('../../../../common/hooks/use_experimental_features'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: jest.fn(() => ({ + pathname: '', + search: '', + })), +})); + const useIsExperimentalFeatureEnabledMock = jest.fn((feature: keyof ExperimentalFeatures) => { if (feature === 'unifiedComponentsInTimelineEnabled') { return true; @@ -79,8 +87,8 @@ const columnsToDisplay = [ ]; // These tests can take more than standard timeout of 5s -// that is why we are setting it to 10s -const SPECIAL_TEST_TIMEOUT = 10000; +// that is why we are increasing the timeout +const SPECIAL_TEST_TIMEOUT = 50000; const localMockedTimelineData = structuredClone(mockTimelineData); @@ -110,6 +118,8 @@ const TestComponent = (props: Partial>) = dataLoadingState: DataLoadingState.loaded, updatedAt: Date.now(), isTextBasedQuery: false, + eventIdToNoteIds: {} as Record, + pinnedEventIds: {} as Record, }; const dispatch = useDispatch(); @@ -188,8 +198,6 @@ describe('unified timeline', () => { }); beforeEach(() => { - const ONE_SECOND = 1000; - jest.setTimeout(10 * ONE_SECOND); HTMLElement.prototype.getBoundingClientRect = jest.fn(() => { return { width: 1000, @@ -216,9 +224,7 @@ describe('unified timeline', () => { ); }); - // Flaky : See https://github.com/elastic/kibana/issues/179831 - // removing/moving column current leads to infitinite loop, will be fixed in further PRs. - describe.skip('columns', () => { + describe('columns', () => { it( 'should move column left correctly ', async () => { @@ -297,7 +303,7 @@ describe('unified timeline', () => { SPECIAL_TEST_TIMEOUT ); - it.skip( + it( 'should remove column ', async () => { const field = { @@ -539,9 +545,7 @@ describe('unified timeline', () => { ); }); - // FLAKY: https://github.com/elastic/kibana/issues/180937 - // FLAKY: https://github.com/elastic/kibana/issues/180956 - describe.skip('unified field list', () => { + describe('unified field list', () => { it( 'should be able to add filters', async () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.tsx index b4daa07f11c40..eaa85e635e4cc 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.tsx @@ -50,6 +50,7 @@ import { timelineActions } from '../../../store'; import type { TimelineModel } from '../../../store/model'; import { getFieldsListCreationOptions } from './get_fields_list_creation_options'; import { defaultUdtHeaders } from './default_headers'; +import type { TimelineDataGridCellContext } from '../types'; const TimelineBodyContainer = styled.div.attrs(({ className = '' }) => ({ className: `${className}`, @@ -119,8 +120,8 @@ interface Props { dataView: DataView; trailingControlColumns?: EuiDataGridProps['trailingControlColumns']; leadingControlColumns?: EuiDataGridProps['leadingControlColumns']; - pinnedEventIds?: TimelineModel['pinnedEventIds']; - eventIdToNoteIds?: TimelineModel['eventIdToNoteIds']; + pinnedEventIds: TimelineModel['pinnedEventIds']; + eventIdToNoteIds: TimelineModel['eventIdToNoteIds']; } const UnifiedTimelineComponent: React.FC = ({ @@ -170,8 +171,10 @@ const UnifiedTimelineComponent: React.FC = ({ } = timelineDataService; const [eventIdsAddingNotes, setEventIdsAddingNotes] = useState>(new Set()); + const onToggleShowNotes = useCallback( - (eventId: string) => { + (eventId?: string) => { + if (!eventId) return; const newSet = new Set(eventIdsAddingNotes); if (newSet.has(eventId)) { newSet.delete(eventId); @@ -370,7 +373,7 @@ const UnifiedTimelineComponent: React.FC = ({ onFieldEdited(); }, [onFieldEdited]); - const cellContext = useMemo(() => { + const cellContext: TimelineDataGridCellContext = useMemo(() => { return { events, pinnedEventIds, diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/table_row_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/table_row_actions.cy.ts new file mode 100644 index 0000000000000..3166f2e7f6b89 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/table_row_actions.cy.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getNewRule } from '../../../objects/rule'; +import { deleteAlertsAndRules } from '../../../tasks/api_calls/common'; +import { createRule } from '../../../tasks/api_calls/rules'; +import { login } from '../../../tasks/login'; +import { visitWithTimeRange } from '../../../tasks/navigation'; +import { openTimelineUsingToggle } from '../../../tasks/security_main'; +import { ALERTS_URL } from '../../../urls/navigation'; +import { + createNewTimeline, + executeTimelineKQL, + executeTimelineSearch, + openTimelineEventContextMenu, +} from '../../../tasks/timeline'; +import { MARK_ALERT_ACKNOWLEDGED_BTN } from '../../../screens/alerts'; +import { GET_TIMELINE_GRID_CELL } from '../../../screens/timeline'; + +describe( + 'Timeline table Row Actions', + { + tags: ['@ess', '@serverless', '@skipInServerlessMKI'], + }, + () => { + beforeEach(() => { + deleteAlertsAndRules(); + createRule(getNewRule()); + login(); + visitWithTimeRange(ALERTS_URL); + openTimelineUsingToggle(); + createNewTimeline(); + executeTimelineSearch('*'); + }); + + it('should refresh the table when alert status is changed', () => { + executeTimelineKQL('kibana.alert.workflow_status:open'); + cy.get(GET_TIMELINE_GRID_CELL('@timestamp')).should('have.length', 1); + openTimelineEventContextMenu(); + cy.get(MARK_ALERT_ACKNOWLEDGED_BTN).click(); + cy.get(GET_TIMELINE_GRID_CELL('@timestamp')).should('have.length', 0); + }); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/unified_components/table_row_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/unified_components/table_row_actions.cy.ts new file mode 100644 index 0000000000000..39fda4d67f244 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/unified_components/table_row_actions.cy.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; +import { getNewRule } from '../../../../objects/rule'; +import { createRule } from '../../../../tasks/api_calls/rules'; +import { MARK_ALERT_ACKNOWLEDGED_BTN } from '../../../../screens/alerts'; +import { GET_UNIFIED_DATA_GRID_CELL } from '../../../../screens/unified_timeline'; +import { login } from '../../../../tasks/login'; +import { visitWithTimeRange } from '../../../../tasks/navigation'; +import { openTimelineUsingToggle } from '../../../../tasks/security_main'; +import { + createNewTimeline, + executeTimelineKQL, + executeTimelineSearch, + openTimelineEventContextMenu, +} from '../../../../tasks/timeline'; +import { ALERTS_URL } from '../../../../urls/navigation'; + +describe( + 'Unified Timeline table Row Actions', + { + tags: ['@ess', '@serverless', '@skipInServerlessMKI'], + env: { + ftrConfig: { + kbnServerArgs: [ + `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'unifiedComponentsInTimelineEnabled', + ])}`, + ], + }, + }, + }, + () => { + beforeEach(() => { + deleteAlertsAndRules(); + createRule(getNewRule()); + login(); + visitWithTimeRange(ALERTS_URL); + openTimelineUsingToggle(); + createNewTimeline(); + executeTimelineSearch('*'); + }); + + it('should refresh the table when alert status is changed', () => { + executeTimelineKQL('kibana.alert.workflow_status:open'); + cy.get(GET_UNIFIED_DATA_GRID_CELL('@timestamp', 0)).should('be.visible'); + openTimelineEventContextMenu(); + cy.get(MARK_ALERT_ACKNOWLEDGED_BTN).click(); + cy.get(GET_UNIFIED_DATA_GRID_CELL('@timestamp', 0)).should('not.exist'); + }); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts index 75c78c24e4dc6..e2bf51be199c9 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts @@ -89,12 +89,14 @@ import { BOTTOM_BAR_TIMELINE_PLUS_ICON, BOTTOM_BAR_CREATE_NEW_TIMELINE, BOTTOM_BAR_CREATE_NEW_TIMELINE_TEMPLATE, + TIMELINE_FLYOUT, } from '../screens/timeline'; import { REFRESH_BUTTON, TIMELINE, TIMELINES_TAB_TEMPLATE } from '../screens/timelines'; import { drag, drop, waitForTabToBeLoaded } from './common'; import { closeFieldsBrowser, filterFieldsBrowser } from './fields_browser'; +import { TIMELINE_CONTEXT_MENU_BTN } from '../screens/alerts'; const hostExistsQuery = 'host.name: *'; @@ -505,3 +507,23 @@ export const selectKqlSearchMode = () => { cy.get(TIMELINE_SEARCH_OR_FILTER).click(); cy.get(TIMELINE_KQLMODE_SEARCH).click(); }; + +export const openTimelineEventContextMenu = (rowIndex: number = 0) => { + cy.get(TIMELINE_FLYOUT).within(() => { + const togglePopover = () => { + cy.get(TIMELINE_CONTEXT_MENU_BTN).eq(rowIndex).should('be.visible'); + cy.get(TIMELINE_CONTEXT_MENU_BTN).eq(rowIndex).click(); + cy.get(TIMELINE_CONTEXT_MENU_BTN) + .first() + .should('be.visible') + .then(($btnEl) => { + if ($btnEl.attr('data-popover-open') !== 'true') { + cy.log(`${TIMELINE_CONTEXT_MENU_BTN} was flaky, attempting to re-open popover`); + togglePopover(); + } + }); + }; + + togglePopover(); + }); +}; From 6e0c68b0b58ce6f718e8f0ce8465563388f6ed8a Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 17 Jun 2024 16:48:59 +0200 Subject: [PATCH 012/127] [ResponseOps][Connectors] Fix alignment of names in the Connectors table (#186275) Fixes #186226 ## Summary Screenshot 2024-06-17 at 12 13 53 --- .../components/actions_connectors_list.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 5f583790d3b8b..d7f5a2beb4c8f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -236,7 +236,7 @@ const ActionsConnectorsList: React.FunctionComponent = () => { const name = getConnectorName(value, item); const link = ( - + Date: Mon, 17 Jun 2024 09:05:54 -0600 Subject: [PATCH 013/127] [Global Search] Provide results for reports and report (#186201) ## Summary Closes https://github.com/elastic/kibana-team/issues/942 ### After ![reports](https://github.com/elastic/kibana/assets/20343860/f5052def-aef9-4165-8934-220046665c59) ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../global_search_bar/public/components/search_bar.test.tsx | 2 +- x-pack/plugins/reporting/public/plugin.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx index 9cebc018daa11..479c3e546dc9c 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx @@ -177,7 +177,7 @@ describe('SearchBar', () => { await focusAndUpdate(); expect(searchService.find).toHaveBeenCalledTimes(1); - // + simulateTypeChar('d'); await assertSearchResults(['Visualize • Kibana', 'Map • Kibana']); diff --git a/x-pack/plugins/reporting/public/plugin.ts b/x-pack/plugins/reporting/public/plugin.ts index 1579bf0cf9377..fe069f7a5d6f5 100644 --- a/x-pack/plugins/reporting/public/plugin.ts +++ b/x-pack/plugins/reporting/public/plugin.ts @@ -148,6 +148,7 @@ export class ReportingPublicPlugin id: 'reporting', title: this.title, order: 3, + keywords: ['reports', 'report', 'reporting'], mount: async (params) => { params.setBreadcrumbs([{ text: this.breadcrumbText }]); const [[coreStart, startDeps], { mountManagementSection }] = await Promise.all([ From 8b6577d6a8724810477a794122124fd9d37a7dbb Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 17 Jun 2024 11:20:19 -0400 Subject: [PATCH 014/127] [Fleet] Display read-only glasses package editor and copy fix (#186127) --- .../applications/fleet/layouts/error.tsx | 2 +- .../edit_package_policy_page/index.tsx | 3 +- .../public/applications/integrations/app.tsx | 23 +++++----- .../integrations/components/header/header.tsx | 42 ++++++++++++++++++- .../hooks/use_read_only_context.tsx | 39 +++++++++++++++++ .../fleet/public/layouts/with_header.tsx | 2 + 6 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 x-pack/plugins/fleet/public/applications/integrations/hooks/use_read_only_context.tsx diff --git a/x-pack/plugins/fleet/public/applications/fleet/layouts/error.tsx b/x-pack/plugins/fleet/public/applications/fleet/layouts/error.tsx index 89e47f3641c95..9f4dad848515d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/layouts/error.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/layouts/error.tsx @@ -71,7 +71,7 @@ export const PermissionsError: React.FunctionComponent<{ ) : ( "All", roleName2: "Read", diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx index 21d25ecdab2c6..0a0ed0b69ca79 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx @@ -19,6 +19,7 @@ import { EuiErrorBoundary, } from '@elastic/eui'; +import { useSetIsReadOnly } from '../../../../integrations/hooks/use_read_only_context'; import { useLink, useBreadcrumbs, @@ -125,7 +126,7 @@ export const EditPackagePolicyForm = memo<{ }); const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies; - + useSetIsReadOnly(canWriteIntegrationPolicies); const newSecrets = useMemo(() => { if (!packageInfo) { return []; diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index 8c052523c31a9..21e2ba249b694 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -40,6 +40,7 @@ import { EPMApp } from './sections/epm'; import { PackageInstallProvider, UIExtensionsContext, FlyoutContextProvider } from './hooks'; import { IntegrationsHeader } from './components/header'; import { AgentEnrollmentFlyout } from './components'; +import { ReadOnlyContextProvider } from './hooks/use_read_only_context'; const queryClient = new QueryClient(); @@ -106,16 +107,18 @@ export const IntegrationsAppContext: React.FC<{ - - - - - {children} - - - + + + + + + {children} + + + + diff --git a/x-pack/plugins/fleet/public/applications/integrations/components/header/header.tsx b/x-pack/plugins/fleet/public/applications/integrations/components/header/header.tsx index 6ca3dc473e10c..30fc0f0d4965f 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/components/header/header.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/components/header/header.tsx @@ -6,11 +6,20 @@ */ import React from 'react'; -import { EuiHeaderSectionItem, EuiHeaderSection, EuiHeaderLinks } from '@elastic/eui'; - +import { FormattedMessage } from '@kbn/i18n-react'; +import { + EuiHeaderSectionItem, + EuiHeaderSection, + EuiHeaderLinks, + useEuiTheme, + EuiToolTip, + EuiButtonEmpty, +} from '@elastic/eui'; +import { css } from '@emotion/css'; import type { AppMountParameters } from '@kbn/core/public'; import type { FleetStartServices } from '../../../../plugin'; +import { useIsReadOnly } from '../../hooks/use_read_only_context'; import { HeaderPortal } from './header_portal'; import { DeploymentDetails } from './deployment_details'; @@ -22,6 +31,14 @@ export const IntegrationsHeader = ({ setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; startServices: Pick; }) => { + const { euiTheme } = useEuiTheme(); + const readOnlyBtnClass = React.useMemo(() => { + return css` + color: ${euiTheme.colors.text}; + `; + }, [euiTheme]); + const isReadOnly = useIsReadOnly(); + return ( @@ -30,6 +47,27 @@ export const IntegrationsHeader = ({ + {isReadOnly ? ( + + + + } + > + + + + + + + ) : null} ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_read_only_context.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_read_only_context.tsx new file mode 100644 index 0000000000000..a1cc117cea673 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_read_only_context.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { createContext, useContext, useEffect, useState } from 'react'; + +const ReadOnlyContext = createContext<{ isReadOnly: boolean; setIsReadOnly: (v: boolean) => void }>( + { isReadOnly: false, setIsReadOnly: () => {} } +); + +export const ReadOnlyContextProvider: React.FC = ({ children }) => { + const [isReadOnly, setIsReadOnly] = useState(false); + return ( + + {children} + + ); +}; + +export function useIsReadOnly() { + const context = useContext(ReadOnlyContext); + return context.isReadOnly; +} + +export function useSetIsReadOnly(isReadOnly: boolean) { + const context = useContext(ReadOnlyContext); + useEffect(() => { + context.setIsReadOnly(true); + return () => context.setIsReadOnly(false); + }, [context]); +} diff --git a/x-pack/plugins/fleet/public/layouts/with_header.tsx b/x-pack/plugins/fleet/public/layouts/with_header.tsx index 81ccc6b92aa74..db500a4633e1e 100644 --- a/x-pack/plugins/fleet/public/layouts/with_header.tsx +++ b/x-pack/plugins/fleet/public/layouts/with_header.tsx @@ -18,6 +18,7 @@ export interface WithHeaderLayoutProps extends HeaderProps { restrictHeaderWidth?: number; 'data-test-subj'?: string; children?: React.ReactNode; + isReadOnly?: boolean; } export const WithHeaderLayout: React.FC = ({ @@ -25,6 +26,7 @@ export const WithHeaderLayout: React.FC = ({ restrictHeaderWidth, children, 'data-test-subj': dataTestSubj, + isReadOnly, ...rest }) => { const isBiggerScreen = useIsWithinMinBreakpoint('xxl'); From 41dc4173c54c2f824a3f1c2a9ad29954ff33ff0b Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Mon, 17 Jun 2024 11:38:04 -0400 Subject: [PATCH 015/127] feat(slo): add burn rate (#184766) --- .../routes/fetch_historical_summary.ts | 15 +-- .../src/rest_specs/routes/find.ts | 3 + .../kbn-slo-schema/src/schema/common.ts | 3 + .../slo/common/constants.ts | 2 +- .../slo/public/data/slo/common.ts | 12 ++ .../slo/public/data/slo/slo.ts | 3 + .../slo/public/locators/slo_edit.test.ts | 2 +- .../slos/components/common/sort_by_select.tsx | 45 ++++++++ .../pages/slos/hooks/use_url_search_state.ts | 10 +- .../public/utils/slo/remote_slo_urls.test.ts | 4 +- .../slo_summary_mappings_template.ts | 39 +++++++ .../slo_summary_pipeline_template.ts | 64 +++++++++++ .../slo_transform_template.test.ts | 4 +- .../slo/server/routes/slo/route.ts | 4 +- .../__snapshots__/create_slo.test.ts.snap | 106 ++++++++++++++++- .../__snapshots__/reset_slo.test.ts.snap | 106 ++++++++++++++++- .../__snapshots__/summary_client.test.ts.snap | 9 ++ .../summary_search_client.test.ts.snap | 16 ++- .../slo/server/services/find_slo.test.ts | 6 + .../slo/server/services/get_slo.test.ts | 6 + .../server/services/summary_client.test.ts | 42 +++---- .../slo/server/services/summary_client.ts | 107 ++++++++++++------ .../server/services/summary_search_client.ts | 18 ++- .../generators/occurrences.ts | 6 +- .../generators/timeslices_calendar_aligned.ts | 6 +- .../generators/timeslices_rolling.ts | 7 +- .../generators/utils.test.ts | 57 ++++++++++ .../generators/utils.ts | 87 ++++++++++++++ .../helpers/create_temp_summary.ts | 32 ++++++ .../apm_transaction_duration.test.ts.snap | 18 +-- .../apm_transaction_error_rate.test.ts.snap | 18 +-- .../__snapshots__/histogram.test.ts.snap | 18 +-- .../__snapshots__/kql_custom.test.ts.snap | 18 +-- .../__snapshots__/metric_custom.test.ts.snap | 12 +- .../timeslice_metric.test.ts.snap | 12 +- .../synthetics_availability.test.ts | 6 +- .../api_integration/apis/slos/create_slo.ts | 78 ++++++++++++- .../api_integration/apis/slos/update_slo.ts | 78 ++++++++++++- .../observability/slos/create_slo.ts | 20 ++-- 39 files changed, 943 insertions(+), 156 deletions(-) create mode 100644 x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.test.ts create mode 100644 x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.ts diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts index 7912c3ccbedc1..84efa2e3b2a5b 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts @@ -16,7 +16,8 @@ import { allOrAnyStringOrArray, dateRangeSchema, dateType, - summarySchema, + errorBudgetSchema, + statusSchema, } from '../../schema/common'; const fetchHistoricalSummaryParamsSchema = t.type({ @@ -41,12 +42,12 @@ const fetchHistoricalSummaryParamsSchema = t.type({ }), }); -const historicalSummarySchema = t.intersection([ - t.type({ - date: dateType, - }), - summarySchema, -]); +const historicalSummarySchema = t.type({ + date: dateType, + status: statusSchema, + sliValue: t.number, + errorBudget: errorBudgetSchema, +}); const fetchHistoricalSummaryResponseSchema = t.array( t.type({ diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find.ts index 31e8c5852a1e1..be7e063ecc80f 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find.ts @@ -14,6 +14,9 @@ const sortBySchema = t.union([ t.literal('error_budget_remaining'), t.literal('sli_value'), t.literal('status'), + t.literal('burn_rate_5m'), + t.literal('burn_rate_1h'), + t.literal('burn_rate_1d'), ]); const findSLOParamsSchema = t.partial({ diff --git a/x-pack/packages/kbn-slo-schema/src/schema/common.ts b/x-pack/packages/kbn-slo-schema/src/schema/common.ts index e2b6d5af0a023..188a5b8f07266 100644 --- a/x-pack/packages/kbn-slo-schema/src/schema/common.ts +++ b/x-pack/packages/kbn-slo-schema/src/schema/common.ts @@ -48,6 +48,9 @@ const summarySchema = t.intersection([ status: statusSchema, sliValue: t.number, errorBudget: errorBudgetSchema, + fiveMinuteBurnRate: t.number, + oneHourBurnRate: t.number, + oneDayBurnRate: t.number, }), t.partial({ summaryUpdatedAt: t.union([t.string, t.null]), diff --git a/x-pack/plugins/observability_solution/slo/common/constants.ts b/x-pack/plugins/observability_solution/slo/common/constants.ts index db0c91ab0ef4b..a70a5fe082730 100644 --- a/x-pack/plugins/observability_solution/slo/common/constants.ts +++ b/x-pack/plugins/observability_solution/slo/common/constants.ts @@ -50,7 +50,7 @@ export const SUPPRESSED_PRIORITY_ACTION = { }; export const SLO_MODEL_VERSION = 2; -export const SLO_RESOURCES_VERSION = 3.2; +export const SLO_RESOURCES_VERSION = 3.3; export const SLO_RESOURCES_VERSION_MAJOR = 3; export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings'; diff --git a/x-pack/plugins/observability_solution/slo/public/data/slo/common.ts b/x-pack/plugins/observability_solution/slo/public/data/slo/common.ts index ae25d150f350b..b9276486c8d8e 100644 --- a/x-pack/plugins/observability_solution/slo/public/data/slo/common.ts +++ b/x-pack/plugins/observability_solution/slo/public/data/slo/common.ts @@ -39,6 +39,9 @@ export const buildHealthySummary = ( remaining: 0.93623, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, ...params, }; }; @@ -55,6 +58,9 @@ export const buildViolatedSummary = ( remaining: -3.1234, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, ...params, }; }; @@ -71,6 +77,9 @@ export const buildNoDataSummary = ( remaining: 1, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, ...params, }; }; @@ -87,6 +96,9 @@ export const buildDegradingSummary = ( remaining: 0.1244, isEstimated: true, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, ...params, }; }; diff --git a/x-pack/plugins/observability_solution/slo/public/data/slo/slo.ts b/x-pack/plugins/observability_solution/slo/public/data/slo/slo.ts index 02541ac8a17c7..ce50190eb7adf 100644 --- a/x-pack/plugins/observability_solution/slo/public/data/slo/slo.ts +++ b/x-pack/plugins/observability_solution/slo/public/data/slo/slo.ts @@ -62,6 +62,9 @@ const baseSlo: Omit = { remaining: 0.936, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, }, groupBy: ALL_VALUE, groupings: {}, diff --git a/x-pack/plugins/observability_solution/slo/public/locators/slo_edit.test.ts b/x-pack/plugins/observability_solution/slo/public/locators/slo_edit.test.ts index ea85e58479636..40fcae8c840ee 100644 --- a/x-pack/plugins/observability_solution/slo/public/locators/slo_edit.test.ts +++ b/x-pack/plugins/observability_solution/slo/public/locators/slo_edit.test.ts @@ -20,7 +20,7 @@ describe('SloEditLocator', () => { it('should return correct url when slo is provided', async () => { const location = await locator.getLocation(buildSlo({ id: 'foo' })); expect(location.path).toEqual( - "/edit/foo?_a=(budgetingMethod:occurrences,createdAt:'2022-12-29T10:11:12.000Z',description:'some%20description%20useful',enabled:!t,groupBy:'*',groupings:(),id:foo,indicator:(params:(filter:'baz:%20foo%20and%20bar%20%3E%202',good:'http_status:%202xx',index:some-index,timestampField:custom_timestamp,total:'a%20query'),type:sli.kql.custom),instanceId:'*',meta:(),name:'super%20important%20level%20service',objective:(target:0.98),revision:1,settings:(frequency:'1m',preventInitialBackfill:!f,syncDelay:'1m'),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:'30d',type:rolling),updatedAt:'2022-12-29T10:11:12.000Z',version:2)" + "/edit/foo?_a=(budgetingMethod:occurrences,createdAt:'2022-12-29T10:11:12.000Z',description:'some%20description%20useful',enabled:!t,groupBy:'*',groupings:(),id:foo,indicator:(params:(filter:'baz:%20foo%20and%20bar%20%3E%202',good:'http_status:%202xx',index:some-index,timestampField:custom_timestamp,total:'a%20query'),type:sli.kql.custom),instanceId:'*',meta:(),name:'super%20important%20level%20service',objective:(target:0.98),revision:1,settings:(frequency:'1m',preventInitialBackfill:!f,syncDelay:'1m'),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),fiveMinuteBurnRate:0,oneDayBurnRate:0,oneHourBurnRate:0,sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:'30d',type:rolling),updatedAt:'2022-12-29T10:11:12.000Z',version:2)" ); }); }); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/sort_by_select.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/sort_by_select.tsx index 3d977a19cb0a8..189dbee8b4f8c 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/sort_by_select.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/sort_by_select.tsx @@ -97,6 +97,51 @@ export function SLOSortBy({ state, onStateChange, loading }: Props) { }); }, }, + { + label: i18n.translate('xpack.slo.list.sortBy.fiveMinuteBurnRate', { + defaultMessage: '5m burn rate', + }), + checked: sortBy === 'burn_rate_5m', + value: 'burn_rate_5m', + onClick: () => { + handleChangeSortBy({ + value: 'burn_rate_5m', + label: i18n.translate('xpack.slo.list.sortBy.fiveMinuteBurnRate', { + defaultMessage: '5m burn rate', + }), + }); + }, + }, + { + label: i18n.translate('xpack.slo.list.sortBy.oneHourBurnRate', { + defaultMessage: '1h burn rate', + }), + checked: sortBy === 'burn_rate_1h', + value: 'burn_rate_1h', + onClick: () => { + handleChangeSortBy({ + value: 'burn_rate_1h', + label: i18n.translate('xpack.slo.list.sortBy.oneHourBurnRate', { + defaultMessage: '1h burn rate', + }), + }); + }, + }, + { + label: i18n.translate('xpack.slo.list.sortBy.oneDayBurnRate', { + defaultMessage: '1d burn rate', + }), + checked: sortBy === 'burn_rate_1d', + value: 'burn_rate_1d', + onClick: () => { + handleChangeSortBy({ + value: 'burn_rate_1d', + label: i18n.translate('xpack.slo.list.sortBy.oneDayBurnRate', { + defaultMessage: '1d burn rate', + }), + }); + }, + }, ]; const groupLabel = sortByOptions.find((option) => option.value === sortBy)?.label || 'Default'; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/hooks/use_url_search_state.ts b/x-pack/plugins/observability_solution/slo/public/pages/slos/hooks/use_url_search_state.ts index a4b842c2ee19f..59284ee617919 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/hooks/use_url_search_state.ts +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/hooks/use_url_search_state.ts @@ -15,7 +15,15 @@ import type { GroupByField } from '../components/slo_list_group_by'; import type { SLOView } from '../components/toggle_slo_view'; export const SLO_LIST_SEARCH_URL_STORAGE_KEY = 'search'; -export type SortField = 'sli_value' | 'error_budget_consumed' | 'error_budget_remaining' | 'status'; +export type SortField = + | 'sli_value' + | 'error_budget_consumed' + | 'error_budget_remaining' + | 'status' + | 'burn_rate_5m' + | 'burn_rate_1h' + | 'burn_rate_1d'; + export type SortDirection = 'asc' | 'desc'; export interface SearchState { diff --git a/x-pack/plugins/observability_solution/slo/public/utils/slo/remote_slo_urls.test.ts b/x-pack/plugins/observability_solution/slo/public/utils/slo/remote_slo_urls.test.ts index 2c8476b9c2e09..3c0495fd1bc9b 100644 --- a/x-pack/plugins/observability_solution/slo/public/utils/slo/remote_slo_urls.test.ts +++ b/x-pack/plugins/observability_solution/slo/public/utils/slo/remote_slo_urls.test.ts @@ -51,7 +51,7 @@ describe('remote SLO URLs Utils', () => { `"https://cloud.elast.co/app/slos/edit/fixed-id"` ); expect(createRemoteSloCloneUrl(remoteSlo)).toMatchInlineSnapshot( - `"https://cloud.elast.co/app/slos/create?_a=(budgetingMethod:occurrences,createdAt:%272022-12-29T10:11:12.000Z%27,description:%27some%20description%20useful%27,enabled:!t,groupBy:%27*%27,groupings:(),indicator:(params:(filter:%27baz:%20foo%20and%20bar%20%3E%202%27,good:%27http_status:%202xx%27,index:some-index,timestampField:custom_timestamp,total:%27a%20query%27),type:sli.kql.custom),instanceId:%27*%27,meta:(),name:%27[Copy]%20super%20important%20level%20service%27,objective:(target:0.98),remote:(kibanaUrl:%27https:/cloud.elast.co/kibana%27,remoteName:remote_cluster),revision:1,settings:(frequency:%271m%27,preventInitialBackfill:!f,syncDelay:%271m%27),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:%2730d%27,type:rolling),updatedAt:%272022-12-29T10:11:12.000Z%27,version:2)"` + `"https://cloud.elast.co/app/slos/create?_a=(budgetingMethod:occurrences,createdAt:%272022-12-29T10:11:12.000Z%27,description:%27some%20description%20useful%27,enabled:!t,groupBy:%27*%27,groupings:(),indicator:(params:(filter:%27baz:%20foo%20and%20bar%20%3E%202%27,good:%27http_status:%202xx%27,index:some-index,timestampField:custom_timestamp,total:%27a%20query%27),type:sli.kql.custom),instanceId:%27*%27,meta:(),name:%27[Copy]%20super%20important%20level%20service%27,objective:(target:0.98),remote:(kibanaUrl:%27https:/cloud.elast.co/kibana%27,remoteName:remote_cluster),revision:1,settings:(frequency:%271m%27,preventInitialBackfill:!f,syncDelay:%271m%27),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),fiveMinuteBurnRate:0,oneDayBurnRate:0,oneHourBurnRate:0,sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:%2730d%27,type:rolling),updatedAt:%272022-12-29T10:11:12.000Z%27,version:2)"` ); }); @@ -71,7 +71,7 @@ describe('remote SLO URLs Utils', () => { `"https://cloud.elast.co/s/my-custom-space/app/slos/edit/fixed-id"` ); expect(createRemoteSloCloneUrl(remoteSlo, 'my-custom-space')).toMatchInlineSnapshot( - `"https://cloud.elast.co/s/my-custom-space/app/slos/create?_a=(budgetingMethod:occurrences,createdAt:%272022-12-29T10:11:12.000Z%27,description:%27some%20description%20useful%27,enabled:!t,groupBy:%27*%27,groupings:(),indicator:(params:(filter:%27baz:%20foo%20and%20bar%20%3E%202%27,good:%27http_status:%202xx%27,index:some-index,timestampField:custom_timestamp,total:%27a%20query%27),type:sli.kql.custom),instanceId:%27*%27,meta:(),name:%27[Copy]%20super%20important%20level%20service%27,objective:(target:0.98),remote:(kibanaUrl:%27https:/cloud.elast.co/kibana%27,remoteName:remote_cluster),revision:1,settings:(frequency:%271m%27,preventInitialBackfill:!f,syncDelay:%271m%27),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:%2730d%27,type:rolling),updatedAt:%272022-12-29T10:11:12.000Z%27,version:2)"` + `"https://cloud.elast.co/s/my-custom-space/app/slos/create?_a=(budgetingMethod:occurrences,createdAt:%272022-12-29T10:11:12.000Z%27,description:%27some%20description%20useful%27,enabled:!t,groupBy:%27*%27,groupings:(),indicator:(params:(filter:%27baz:%20foo%20and%20bar%20%3E%202%27,good:%27http_status:%202xx%27,index:some-index,timestampField:custom_timestamp,total:%27a%20query%27),type:sli.kql.custom),instanceId:%27*%27,meta:(),name:%27[Copy]%20super%20important%20level%20service%27,objective:(target:0.98),remote:(kibanaUrl:%27https:/cloud.elast.co/kibana%27,remoteName:remote_cluster),revision:1,settings:(frequency:%271m%27,preventInitialBackfill:!f,syncDelay:%271m%27),summary:(errorBudget:(consumed:0.064,initial:0.02,isEstimated:!f,remaining:0.936),fiveMinuteBurnRate:0,oneDayBurnRate:0,oneHourBurnRate:0,sliValue:0.99872,status:HEALTHY),tags:!(k8s,production,critical),timeWindow:(duration:%2730d%27,type:rolling),updatedAt:%272022-12-29T10:11:12.000Z%27,version:2)"` ); }); }); diff --git a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts index b0509495e8e79..d25722e4f323d 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/component_templates/slo_summary_mappings_template.ts @@ -178,6 +178,45 @@ export const getSLOSummaryMappingsTemplate = ( spaceId: { type: 'keyword', }, + fiveMinuteBurnRate: { + properties: { + goodEvents: { + type: 'long', + }, + totalEvents: { + type: 'long', + }, + value: { + type: 'double', + }, + }, + }, + oneHourBurnRate: { + properties: { + goodEvents: { + type: 'long', + }, + totalEvents: { + type: 'long', + }, + value: { + type: 'double', + }, + }, + }, + oneDayBurnRate: { + properties: { + goodEvents: { + type: 'long', + }, + totalEvents: { + type: 'long', + }, + value: { + type: 'double', + }, + }, + }, }, }, }, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts index d3b4aed69f1c0..7d51ffeddea4b 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts @@ -194,6 +194,46 @@ export const getSLOSummaryPipelineTemplate = ( ignore_failure: true, }, }, + // >= 8.15: + { + script: { + description: 'Computes the last five minute burn rate value', + lang: 'painless', + params: { + isTimeslice: timeslicesBudgetingMethodSchema.is(slo.budgetingMethod), + totalSlicesInRange: timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) + ? Math.floor(5 / slo.objective.timesliceWindow!.asMinutes()) + : 0, + }, + source: getBurnRateSource('fiveMinuteBurnRate'), + }, + }, + { + script: { + description: 'Computes the last hour burn rate value', + lang: 'painless', + params: { + isTimeslice: timeslicesBudgetingMethodSchema.is(slo.budgetingMethod), + totalSlicesInRange: timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) + ? Math.floor(60 / slo.objective.timesliceWindow!.asMinutes()) + : 0, + }, + source: getBurnRateSource('oneHourBurnRate'), + }, + }, + { + script: { + description: 'Computes the last day burn rate value', + lang: 'painless', + params: { + isTimeslice: timeslicesBudgetingMethodSchema.is(slo.budgetingMethod), + totalSlicesInRange: timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) + ? Math.floor(1440 / slo.objective.timesliceWindow!.asMinutes()) + : 0, + }, + source: getBurnRateSource('oneDayBurnRate'), + }, + }, ], _meta: { description: `Ingest pipeline for SLO summary data [id: ${slo.id}, revision: ${slo.revision}]`, @@ -203,3 +243,27 @@ export const getSLOSummaryPipelineTemplate = ( }, }; }; + +function getBurnRateSource( + burnRateKey: 'oneDayBurnRate' | 'oneHourBurnRate' | 'fiveMinuteBurnRate' +): string { + return `def totalEvents = ctx["${burnRateKey}"]["totalEvents"]; + def goodEvents = ctx["${burnRateKey}"]["goodEvents"]; + def errorBudgetInitial = ctx["errorBudgetInitial"]; + + if (totalEvents == null || totalEvents == 0) { + ctx["${burnRateKey}"]["value"] = 0.0; + return; + } + + def totalSlicesInRange = params["totalSlicesInRange"]; + def isTimeslice = params["isTimeslice"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx["${burnRateKey}"]["value"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx["${burnRateKey}"]["value"] = (1.0 - sliValue) / errorBudgetInitial; + }`; +} diff --git a/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.test.ts b/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.test.ts index 535c8295516af..d3c0a9ea67b5d 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/transform_templates/slo_transform_template.test.ts @@ -143,7 +143,7 @@ describe('slo transform template', () => { }, defer_validation: true, _meta: { - version: 3.2, + version: 3.3, managed: true, managed_by: 'observability', }, @@ -247,7 +247,7 @@ describe('slo transform template', () => { }, defer_validation: true, _meta: { - version: 3.2, + version: 3.3, managed: true, managed_by: 'observability', }, diff --git a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts index f5075abac0c0a..1f4c3ee2e3bb3 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts @@ -33,6 +33,7 @@ import { GetSLOsOverview } from '../../services/get_slos_overview'; import type { IndicatorTypes } from '../../domain/models'; import { CreateSLO, + DefaultBurnRatesClient, DefaultSummaryClient, DefaultSummaryTransformManager, DefaultTransformManager, @@ -295,7 +296,8 @@ const getSLORoute = createSloServerRoute({ const soClient = (await context.core).savedObjects.client; const esClient = (await context.core).elasticsearch.client.asCurrentUser; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const summaryClient = new DefaultSummaryClient(esClient); + const burnRatesClient = new DefaultBurnRatesClient(esClient); + const summaryClient = new DefaultSummaryClient(esClient, burnRatesClient); const defintionClient = new SloDefinitionClient(repository, esClient, logger); const getSLO = new GetSLO(defintionClient, summaryClient); diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap index 6303588a918a6..8416373c460bf 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap @@ -7,7 +7,7 @@ Array [ "description": "Ingest pipeline for SLO summary data [id: unique-id, revision: 1]", "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "description": "Ingest pipeline for SLO summary data [id: unique-id, revision: 1]", "id": ".slo-observability.summary.pipeline-unique-id-1", @@ -166,6 +166,93 @@ Array [ "value": "http://myhost.com/mock-server-basepath", }, }, + Object { + "script": Object { + "description": "Computes the last five minute burn rate value", + "lang": "painless", + "params": Object { + "isTimeslice": false, + "totalSlicesInRange": 0, + }, + "source": "def totalEvents = ctx[\\"fiveMinuteBurnRate\\"][\\"totalEvents\\"]; + def goodEvents = ctx[\\"fiveMinuteBurnRate\\"][\\"goodEvents\\"]; + def errorBudgetInitial = ctx[\\"errorBudgetInitial\\"]; + + if (totalEvents == null || totalEvents == 0) { + ctx[\\"fiveMinuteBurnRate\\"][\\"value\\"] = 0.0; + return; + } + + def totalSlicesInRange = params[\\"totalSlicesInRange\\"]; + def isTimeslice = params[\\"isTimeslice\\"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx[\\"fiveMinuteBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx[\\"fiveMinuteBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + }", + }, + }, + Object { + "script": Object { + "description": "Computes the last hour burn rate value", + "lang": "painless", + "params": Object { + "isTimeslice": false, + "totalSlicesInRange": 0, + }, + "source": "def totalEvents = ctx[\\"oneHourBurnRate\\"][\\"totalEvents\\"]; + def goodEvents = ctx[\\"oneHourBurnRate\\"][\\"goodEvents\\"]; + def errorBudgetInitial = ctx[\\"errorBudgetInitial\\"]; + + if (totalEvents == null || totalEvents == 0) { + ctx[\\"oneHourBurnRate\\"][\\"value\\"] = 0.0; + return; + } + + def totalSlicesInRange = params[\\"totalSlicesInRange\\"]; + def isTimeslice = params[\\"isTimeslice\\"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx[\\"oneHourBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx[\\"oneHourBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + }", + }, + }, + Object { + "script": Object { + "description": "Computes the last day burn rate value", + "lang": "painless", + "params": Object { + "isTimeslice": false, + "totalSlicesInRange": 0, + }, + "source": "def totalEvents = ctx[\\"oneDayBurnRate\\"][\\"totalEvents\\"]; + def goodEvents = ctx[\\"oneDayBurnRate\\"][\\"goodEvents\\"]; + def errorBudgetInitial = ctx[\\"errorBudgetInitial\\"]; + + if (totalEvents == null || totalEvents == 0) { + ctx[\\"oneDayBurnRate\\"][\\"value\\"] = 0.0; + return; + } + + def totalSlicesInRange = params[\\"totalSlicesInRange\\"]; + def isTimeslice = params[\\"isTimeslice\\"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx[\\"oneDayBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx[\\"oneDayBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + }", + }, + }, ], }, ] @@ -179,6 +266,11 @@ Array [ "errorBudgetEstimated": false, "errorBudgetInitial": 0.010000000000000009, "errorBudgetRemaining": 1, + "fiveMinuteBurnRate": Object { + "goodEvents": 0, + "totalEvents": 0, + "value": 0, + }, "goodEvents": 0, "isTempDoc": true, "kibanaUrl": "http://myhost.com/mock-server-basepath", @@ -193,6 +285,16 @@ Array [ }, "name": null, }, + "oneDayBurnRate": Object { + "goodEvents": 0, + "totalEvents": 0, + "value": 0, + }, + "oneHourBurnRate": Object { + "goodEvents": 0, + "totalEvents": 0, + "value": 0, + }, "service": Object { "environment": "irrelevant", "name": "irrelevant", @@ -241,7 +343,7 @@ Array [ }, }, "id": "slo-unique-id", - "index": ".slo-observability.summary-v3.2.temp", + "index": ".slo-observability.summary-v3.3.temp", "refresh": true, }, ] diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap index 9d231462c03af..721402bc88961 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap @@ -203,7 +203,7 @@ exports[`ResetSLO resets all associated resources 8`] = ` "description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]", "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "description": "Ingest pipeline for SLO summary data [id: irrelevant, revision: 1]", "id": ".slo-observability.summary.pipeline-irrelevant-1", @@ -366,6 +366,93 @@ exports[`ResetSLO resets all associated resources 8`] = ` "value": "http://myhost.com/mock-server-basepath", }, }, + Object { + "script": Object { + "description": "Computes the last five minute burn rate value", + "lang": "painless", + "params": Object { + "isTimeslice": false, + "totalSlicesInRange": 0, + }, + "source": "def totalEvents = ctx[\\"fiveMinuteBurnRate\\"][\\"totalEvents\\"]; + def goodEvents = ctx[\\"fiveMinuteBurnRate\\"][\\"goodEvents\\"]; + def errorBudgetInitial = ctx[\\"errorBudgetInitial\\"]; + + if (totalEvents == null || totalEvents == 0) { + ctx[\\"fiveMinuteBurnRate\\"][\\"value\\"] = 0.0; + return; + } + + def totalSlicesInRange = params[\\"totalSlicesInRange\\"]; + def isTimeslice = params[\\"isTimeslice\\"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx[\\"fiveMinuteBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx[\\"fiveMinuteBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + }", + }, + }, + Object { + "script": Object { + "description": "Computes the last hour burn rate value", + "lang": "painless", + "params": Object { + "isTimeslice": false, + "totalSlicesInRange": 0, + }, + "source": "def totalEvents = ctx[\\"oneHourBurnRate\\"][\\"totalEvents\\"]; + def goodEvents = ctx[\\"oneHourBurnRate\\"][\\"goodEvents\\"]; + def errorBudgetInitial = ctx[\\"errorBudgetInitial\\"]; + + if (totalEvents == null || totalEvents == 0) { + ctx[\\"oneHourBurnRate\\"][\\"value\\"] = 0.0; + return; + } + + def totalSlicesInRange = params[\\"totalSlicesInRange\\"]; + def isTimeslice = params[\\"isTimeslice\\"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx[\\"oneHourBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx[\\"oneHourBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + }", + }, + }, + Object { + "script": Object { + "description": "Computes the last day burn rate value", + "lang": "painless", + "params": Object { + "isTimeslice": false, + "totalSlicesInRange": 0, + }, + "source": "def totalEvents = ctx[\\"oneDayBurnRate\\"][\\"totalEvents\\"]; + def goodEvents = ctx[\\"oneDayBurnRate\\"][\\"goodEvents\\"]; + def errorBudgetInitial = ctx[\\"errorBudgetInitial\\"]; + + if (totalEvents == null || totalEvents == 0) { + ctx[\\"oneDayBurnRate\\"][\\"value\\"] = 0.0; + return; + } + + def totalSlicesInRange = params[\\"totalSlicesInRange\\"]; + def isTimeslice = params[\\"isTimeslice\\"]; + if (isTimeslice && totalSlicesInRange > 0) { + def badEvents = (double)totalEvents - (double)goodEvents; + def sliValue = 1.0 - (badEvents / (double)totalSlicesInRange); + ctx[\\"oneDayBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + } else { + def sliValue = (double)goodEvents / (double)totalEvents; + ctx[\\"oneDayBurnRate\\"][\\"value\\"] = (1.0 - sliValue) / errorBudgetInitial; + }", + }, + }, ], }, ], @@ -468,6 +555,11 @@ exports[`ResetSLO resets all associated resources 11`] = ` "errorBudgetEstimated": false, "errorBudgetInitial": 0.0010000000000000009, "errorBudgetRemaining": 1, + "fiveMinuteBurnRate": Object { + "goodEvents": 0, + "totalEvents": 0, + "value": 0, + }, "goodEvents": 0, "isTempDoc": true, "kibanaUrl": "http://myhost.com/mock-server-basepath", @@ -482,6 +574,16 @@ exports[`ResetSLO resets all associated resources 11`] = ` }, "name": null, }, + "oneDayBurnRate": Object { + "goodEvents": 0, + "totalEvents": 0, + "value": 0, + }, + "oneHourBurnRate": Object { + "goodEvents": 0, + "totalEvents": 0, + "value": 0, + }, "service": Object { "environment": "irrelevant", "name": "irrelevant", @@ -534,7 +636,7 @@ exports[`ResetSLO resets all associated resources 11`] = ` }, }, "id": "slo-irrelevant", - "index": ".slo-observability.summary-v3.2.temp", + "index": ".slo-observability.summary-v3.3.temp", "refresh": true, }, ], diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_client.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_client.test.ts.snap index 15ed30430fea7..83e4a7af010d5 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_client.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_client.test.ts.snap @@ -11,6 +11,9 @@ Object { "isEstimated": false, "remaining": 0.80158, }, + "fiveMinuteBurnRate": 0.5, + "oneDayBurnRate": 0.7, + "oneHourBurnRate": 0.6, "sliValue": 0.990079, "status": "HEALTHY", }, @@ -28,6 +31,9 @@ Object { "isEstimated": false, "remaining": -99, }, + "fiveMinuteBurnRate": 0.5, + "oneDayBurnRate": 0.7, + "oneHourBurnRate": 0.6, "sliValue": 0.9, "status": "VIOLATED", }, @@ -45,6 +51,9 @@ Object { "isEstimated": false, "remaining": 0.80158, }, + "fiveMinuteBurnRate": 0.5, + "oneDayBurnRate": 0.7, + "oneHourBurnRate": 0.6, "sliValue": 0.990079, "status": "HEALTHY", }, diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_search_client.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_search_client.test.ts.snap index 76a022867cfcf..3aee32ab1b546 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_search_client.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/summary_search_client.test.ts.snap @@ -1,6 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP - exports[`Summary Search Client returns the summary documents without duplicate temporary summary documents 1`] = ` Array [ Object { @@ -47,6 +46,9 @@ Object { "isEstimated": false, "remaining": 1, }, + "fiveMinuteBurnRate": 0, + "oneDayBurnRate": 0, + "oneHourBurnRate": 0, "sliValue": -1, "status": "NO_DATA", "summaryUpdatedAt": null, @@ -63,6 +65,9 @@ Object { "isEstimated": false, "remaining": 1, }, + "fiveMinuteBurnRate": 0, + "oneDayBurnRate": 0, + "oneHourBurnRate": 0, "sliValue": -1, "status": "NO_DATA", "summaryUpdatedAt": null, @@ -79,6 +84,9 @@ Object { "isEstimated": false, "remaining": 1, }, + "fiveMinuteBurnRate": 0, + "oneDayBurnRate": 0, + "oneHourBurnRate": 0, "sliValue": -1, "status": "NO_DATA", "summaryUpdatedAt": null, @@ -95,6 +103,9 @@ Object { "isEstimated": false, "remaining": 1, }, + "fiveMinuteBurnRate": 0, + "oneDayBurnRate": 0, + "oneHourBurnRate": 0, "sliValue": -1, "status": "NO_DATA", "summaryUpdatedAt": null, @@ -111,6 +122,9 @@ Object { "isEstimated": false, "remaining": 1, }, + "fiveMinuteBurnRate": 0, + "oneDayBurnRate": 0, + "oneHourBurnRate": 0, "sliValue": -1, "status": "NO_DATA", "summaryUpdatedAt": null, diff --git a/x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts index 183d4beee19dd..bb26ab235c9f4 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/find_slo.test.ts @@ -91,6 +91,9 @@ describe('FindSLO', () => { remaining: 0.9, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, }, tags: ['critical', 'k8s'], createdAt: slo.createdAt.toISOString(), @@ -180,6 +183,9 @@ function summarySearchResult(slo: SLODefinition): Paginated { remaining: 0.9, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, }, }, ], diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts index 49421887d3d8e..a3665294ab5c2 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo.test.ts @@ -49,6 +49,9 @@ describe('GetSLO', () => { remaining: 0.9, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, }, }); @@ -91,6 +94,9 @@ describe('GetSLO', () => { remaining: 0.9, isEstimated: false, }, + fiveMinuteBurnRate: 0, + oneHourBurnRate: 0, + oneDayBurnRate: 0, }, tags: ['critical', 'k8s'], createdAt: slo.createdAt.toISOString(), diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts index 584aba75e22ff..120285f374f4d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_client.test.ts @@ -9,8 +9,10 @@ import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/ser import moment from 'moment'; import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { Duration, DurationUnit } from '../domain/models'; +import { BurnRatesClient } from './burn_rates_client'; import { createSLO } from './fixtures/slo'; import { sevenDaysRolling, weeklyCalendarAligned } from './fixtures/time_window'; +import { createBurnRatesClientMock } from './mocks'; import { DefaultSummaryClient } from './summary_client'; const createEsResponse = (good: number = 90, total: number = 100) => ({ @@ -33,9 +35,17 @@ const createEsResponse = (good: number = 90, total: number = 100) => ({ describe('SummaryClient', () => { let esClientMock: ElasticsearchClientMock; + let burnRatesClientMock: jest.Mocked; beforeEach(() => { esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + burnRatesClientMock = createBurnRatesClientMock(); + + burnRatesClientMock.calculate.mockResolvedValueOnce([ + { name: '5m', burnRate: 0.5, sli: 0.9 }, + { name: '1h', burnRate: 0.6, sli: 0.9 }, + { name: '1d', burnRate: 0.7, sli: 0.9 }, + ]); }); describe('fetchSummary', () => { @@ -43,7 +53,7 @@ describe('SummaryClient', () => { it('returns the summary', async () => { const slo = createSLO({ timeWindow: sevenDaysRolling() }); esClientMock.search.mockResolvedValueOnce(createEsResponse()); - const summaryClient = new DefaultSummaryClient(esClientMock); + const summaryClient = new DefaultSummaryClient(esClientMock, burnRatesClientMock); const result = await summaryClient.computeSummary({ slo }); @@ -78,7 +88,7 @@ describe('SummaryClient', () => { timeWindow: weeklyCalendarAligned(), }); esClientMock.search.mockResolvedValueOnce(createEsResponse()); - const summaryClient = new DefaultSummaryClient(esClientMock); + const summaryClient = new DefaultSummaryClient(esClientMock, burnRatesClientMock); await summaryClient.computeSummary({ slo }); @@ -121,7 +131,7 @@ describe('SummaryClient', () => { timeWindow: sevenDaysRolling(), }); esClientMock.search.mockResolvedValueOnce(createEsResponse()); - const summaryClient = new DefaultSummaryClient(esClientMock); + const summaryClient = new DefaultSummaryClient(esClientMock, burnRatesClientMock); const result = await summaryClient.computeSummary({ slo }); @@ -143,16 +153,8 @@ describe('SummaryClient', () => { }, }, aggs: { - good: { - sum: { - field: 'slo.isGoodSlice', - }, - }, - total: { - value_count: { - field: 'slo.isGoodSlice', - }, - }, + good: { sum: { field: 'slo.isGoodSlice' } }, + total: { value_count: { field: 'slo.isGoodSlice' } }, }, }); }); @@ -170,7 +172,7 @@ describe('SummaryClient', () => { timeWindow: weeklyCalendarAligned(), }); esClientMock.search.mockResolvedValueOnce(createEsResponse()); - const summaryClient = new DefaultSummaryClient(esClientMock); + const summaryClient = new DefaultSummaryClient(esClientMock, burnRatesClientMock); const result = await summaryClient.computeSummary({ slo }); @@ -196,16 +198,8 @@ describe('SummaryClient', () => { }, }, aggs: { - good: { - sum: { - field: 'slo.isGoodSlice', - }, - }, - total: { - value_count: { - field: 'slo.isGoodSlice', - }, - }, + good: { sum: { field: 'slo.isGoodSlice' } }, + total: { value_count: { field: 'slo.isGoodSlice' } }, }, }); }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts index 635dbdd654ead..0b9ee20062d1e 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { AggregationsValueCountAggregate } from '@elastic/elasticsearch/lib/api/types'; import { AggregationsSumAggregate, AggregationsTopHitsAggregate, @@ -13,13 +14,16 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { ALL_VALUE, calendarAlignedTimeWindowSchema, + Duration, + DurationUnit, occurrencesBudgetingMethodSchema, timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; -import { Groupings, Meta, SLODefinition, Summary } from '../domain/models'; +import { DateRange, Groupings, Meta, SLODefinition, Summary } from '../domain/models'; import { computeSLI, computeSummaryStatus, toErrorBudget } from '../domain/services'; import { toDateRange } from '../domain/services/date_range'; +import { BurnRatesClient } from './burn_rates_client'; import { getFlattenedGroupings } from './utils'; import { computeTotalSlicesFromDateRange } from './utils/compute_total_slices_from_date_range'; @@ -44,7 +48,7 @@ export interface SummaryClient { } export class DefaultSummaryClient implements SummaryClient { - constructor(private esClient: ElasticsearchClient) {} + constructor(private esClient: ElasticsearchClient, private burnRatesClient: BurnRatesClient) {} async computeSummary({ slo, instanceId, remoteName }: Params): Promise { const dateRange = toDateRange(slo.timeWindow); @@ -103,45 +107,25 @@ export class DefaultSummaryClient implements SummaryClient { }, }, }), - ...(timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) && { - good: { - sum: { field: 'slo.isGoodSlice' }, - }, - total: { - value_count: { field: 'slo.isGoodSlice' }, - }, - }), - ...(occurrencesBudgetingMethodSchema.is(slo.budgetingMethod) && { - good: { sum: { field: 'slo.numerator' } }, - total: { sum: { field: 'slo.denominator' } }, - }), + ...buildAggs(slo), }, }); - const good = result.aggregations?.good?.value ?? 0; - const total = result.aggregations?.total?.value ?? 0; const source = result.aggregations?.last_doc?.hits?.hits?.[0]?._source; const groupings = source?.slo?.groupings; - let sliValue; - if (timeslicesBudgetingMethodSchema.is(slo.budgetingMethod)) { - const totalSlices = computeTotalSlicesFromDateRange( - dateRange, - slo.objective.timesliceWindow! - ); - - sliValue = computeSLI(good, total, totalSlices); - } else { - sliValue = computeSLI(good, total); - } - - const initialErrorBudget = 1 - slo.objective.target; - const consumedErrorBudget = sliValue < 0 ? 0 : (1 - sliValue) / initialErrorBudget; - const errorBudget = toErrorBudget( - initialErrorBudget, - consumedErrorBudget, - calendarAlignedTimeWindowSchema.is(slo.timeWindow) && - occurrencesBudgetingMethodSchema.is(slo.budgetingMethod) + const sliValue = computeSliValue(slo, dateRange, result.aggregations); + const errorBudget = computeErrorBudget(slo, sliValue); + + const burnRates = await this.burnRatesClient.calculate( + slo, + instanceId ?? ALL_VALUE, + [ + { name: '5m', duration: new Duration(5, DurationUnit.Minute) }, + { name: '1h', duration: new Duration(1, DurationUnit.Hour) }, + { name: '1d', duration: new Duration(1, DurationUnit.Day) }, + ], + remoteName ); return { @@ -149,6 +133,9 @@ export class DefaultSummaryClient implements SummaryClient { sliValue, errorBudget, status: computeSummaryStatus(slo.objective, sliValue, errorBudget), + fiveMinuteBurnRate: getBurnRate('5m', burnRates), + oneHourBurnRate: getBurnRate('1h', burnRates), + oneDayBurnRate: getBurnRate('1d', burnRates), }, groupings: groupings ? getFlattenedGroupings({ groupBy: slo.groupBy, groupings }) : {}, meta: getMetaFields(slo, source ?? {}), @@ -156,6 +143,18 @@ export class DefaultSummaryClient implements SummaryClient { } } +function buildAggs(slo: SLODefinition) { + return timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) + ? { + good: { sum: { field: 'slo.isGoodSlice' } }, + total: { value_count: { field: 'slo.isGoodSlice' } }, + } + : { + good: { sum: { field: 'slo.numerator' } }, + total: { sum: { field: 'slo.denominator' } }, + }; +} + function getMetaFields( slo: SLODefinition, source: { monitor?: { id?: string }; config_id?: string; observer?: { name?: string } } @@ -176,3 +175,41 @@ function getMetaFields( return {}; } } + +interface BurnRateBucket { + good: AggregationsSumAggregate; + total: AggregationsSumAggregate | AggregationsValueCountAggregate; +} + +function computeSliValue( + slo: SLODefinition, + dateRange: DateRange, + bucket: BurnRateBucket | undefined +) { + const good = bucket?.good?.value ?? 0; + const total = bucket?.total?.value ?? 0; + + if (timeslicesBudgetingMethodSchema.is(slo.budgetingMethod)) { + const totalSlices = computeTotalSlicesFromDateRange(dateRange, slo.objective.timesliceWindow!); + + return computeSLI(good, total, totalSlices); + } + + return computeSLI(good, total); +} + +function computeErrorBudget(slo: SLODefinition, sliValue: number) { + const initialErrorBudget = 1 - slo.objective.target; + const consumedErrorBudget = sliValue < 0 ? 0 : (1 - sliValue) / initialErrorBudget; + + return toErrorBudget( + initialErrorBudget, + consumedErrorBudget, + calendarAlignedTimeWindowSchema.is(slo.timeWindow) && + occurrencesBudgetingMethodSchema.is(slo.budgetingMethod) + ); +} + +function getBurnRate(burnRateWindow: string, burnRates: Array<{ name: string; burnRate: number }>) { + return burnRates.find(({ name }) => name === burnRateWindow)?.burnRate ?? 0; +} diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts index d99679fe01ac0..6493e613bbedc 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_search_client.ts @@ -33,7 +33,14 @@ export interface SummaryResult { }; } -type SortField = 'error_budget_consumed' | 'error_budget_remaining' | 'sli_value' | 'status'; +type SortField = + | 'error_budget_consumed' + | 'error_budget_remaining' + | 'sli_value' + | 'status' + | 'burn_rate_5m' + | 'burn_rate_1h' + | 'burn_rate_1d'; export interface Sort { field: SortField; @@ -158,6 +165,9 @@ export class DefaultSummarySearchClient implements SummarySearchClient { sliValue: toHighPrecision(doc._source.sliValue), status: summaryDoc.status, summaryUpdatedAt: summaryDoc.summaryUpdatedAt, + fiveMinuteBurnRate: toHighPrecision(summaryDoc.fiveMinuteBurnRate?.value ?? 0), + oneHourBurnRate: toHighPrecision(summaryDoc.oneHourBurnRate?.value ?? 0), + oneDayBurnRate: toHighPrecision(summaryDoc.oneDayBurnRate?.value ?? 0), }, groupings: getFlattenedGroupings({ groupings: summaryDoc.slo.groupings, @@ -230,6 +240,12 @@ function toDocumentSortField(field: SortField) { return 'status'; case 'sli_value': return 'sliValue'; + case 'burn_rate_5m': + return 'fiveMinuteBurnRate.value'; + case 'burn_rate_1h': + return 'oneHourBurnRate.value'; + case 'burn_rate_1d': + return 'oneDayBurnRate.value'; default: assertNever(field); } diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts index 88d83a486d6c0..1dd2c0758096c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/occurrences.ts @@ -6,7 +6,6 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLODefinition } from '../../../domain/models'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, @@ -14,7 +13,9 @@ import { SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_NAME, } from '../../../../common/constants'; +import { SLODefinition } from '../../../domain/models'; import { getGroupBy } from './common'; +import { buildBurnRateAgg } from './utils'; export function generateSummaryTransformForOccurrences( slo: SLODefinition @@ -115,6 +116,9 @@ export function generateSummaryTransformForOccurrences( field: '@timestamp', }, }, + ...buildBurnRateAgg('fiveMinuteBurnRate', slo), + ...buildBurnRateAgg('oneHourBurnRate', slo), + ...buildBurnRateAgg('oneDayBurnRate', slo), }, }, description: `Summarise the rollup data of SLO: ${slo.name} [id: ${slo.id}, revision: ${slo.revision}].`, diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts index b0304316583b7..f5db77467c94d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts @@ -6,7 +6,6 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { DurationUnit, SLODefinition } from '../../../domain/models'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, @@ -14,7 +13,9 @@ import { SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_NAME, } from '../../../../common/constants'; +import { DurationUnit, SLODefinition } from '../../../domain/models'; import { getGroupBy } from './common'; +import { buildBurnRateAgg } from './utils'; export function generateSummaryTransformForTimeslicesAndCalendarAligned( slo: SLODefinition @@ -142,6 +143,9 @@ export function generateSummaryTransformForTimeslicesAndCalendarAligned( field: '@timestamp', }, }, + ...buildBurnRateAgg('fiveMinuteBurnRate', slo), + ...buildBurnRateAgg('oneHourBurnRate', slo), + ...buildBurnRateAgg('oneDayBurnRate', slo), }, }, description: `Summarise the rollup data of SLO: ${slo.name} [id: ${slo.id}, revision: ${slo.revision}].`, diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts index 24273dd5c037d..05724cb9e43d6 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts @@ -6,7 +6,6 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLODefinition } from '../../../domain/models'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, @@ -14,7 +13,9 @@ import { SLO_RESOURCES_VERSION, SLO_SUMMARY_DESTINATION_INDEX_NAME, } from '../../../../common/constants'; +import { SLODefinition } from '../../../domain/models'; import { getGroupBy } from './common'; +import { buildBurnRateAgg } from './utils'; export function generateSummaryTransformForTimeslicesAndRolling( slo: SLODefinition @@ -118,6 +119,10 @@ export function generateSummaryTransformForTimeslicesAndRolling( field: '@timestamp', }, }, + + ...buildBurnRateAgg('fiveMinuteBurnRate', slo), + ...buildBurnRateAgg('oneHourBurnRate', slo), + ...buildBurnRateAgg('oneDayBurnRate', slo), }, }, description: `Summarise the rollup data of SLO: ${slo.name} [id: ${slo.id}, revision: ${slo.revision}].`, diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.test.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.test.ts new file mode 100644 index 0000000000000..660c0bd18abff --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { twoMinute } from '../../fixtures/duration'; +import { createSLOWithTimeslicesBudgetingMethod, createSLO } from '../../fixtures/slo'; +import { getFiveMinuteRange, getOneDayRange, getOneHourRange } from './utils'; + +describe('getFiveMinuteRange', () => { + it('should return range for 5 minutes including slo delay', () => { + const slo = createSLOWithTimeslicesBudgetingMethod({ + objective: { + target: 0.98, + timesliceTarget: 0.9, + timesliceWindow: twoMinute(), + }, + }); + + const range = getFiveMinuteRange(slo); + expect(range).toEqual({ + gte: `now-540s/m`, + lte: `now-240s/m`, + }); + }); +}); + +describe('getOneHourRange', () => { + it('should return range for 1 hour including slo delay', () => { + const slo = createSLOWithTimeslicesBudgetingMethod({ + objective: { + target: 0.98, + timesliceTarget: 0.9, + timesliceWindow: twoMinute(), + }, + }); + const range = getOneHourRange(slo); + expect(range).toEqual({ + gte: `now-3840s/m`, + lte: `now-240s/m`, + }); + }); +}); + +describe('getOneDayRange', () => { + it('should return range for 1 day including slo delay', () => { + const slo = createSLO(); + + const range = getOneDayRange(slo); + expect(range).toEqual({ + gte: `now-86580s/m`, + lte: `now-180s/m`, + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.ts new file mode 100644 index 0000000000000..fb1ec8aa5eadc --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/generators/utils.ts @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { occurrencesBudgetingMethodSchema, timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; +import { SLODefinition } from '../../../domain/models'; +import { getDelayInSecondsFromSLO } from '../../../domain/services/get_delay_in_seconds_from_slo'; + +const FIVE_MINUTES_IN_SECONDS = 300; +const ONE_HOUR_IN_SECONDS = 3600; +const ONE_DAY_IN_SECONDS = 86400; + +export function getFiveMinuteRange(slo: SLODefinition) { + const delayInSeconds = getDelayInSecondsFromSLO(slo); + return { + gte: `now-${FIVE_MINUTES_IN_SECONDS + delayInSeconds}s/m`, + lte: `now-${delayInSeconds}s/m`, + }; +} + +export function getOneHourRange(slo: SLODefinition) { + const delayInSeconds = getDelayInSecondsFromSLO(slo); + return { + gte: `now-${ONE_HOUR_IN_SECONDS + delayInSeconds}s/m`, + lte: `now-${delayInSeconds}s/m`, + }; +} + +export function getOneDayRange(slo: SLODefinition) { + const delayInSeconds = getDelayInSecondsFromSLO(slo); + return { + gte: `now-${ONE_DAY_IN_SECONDS + delayInSeconds}s/m`, + lte: `now-${delayInSeconds}s/m`, + }; +} + +export function buildBurnRateAgg( + aggKey: 'fiveMinuteBurnRate' | 'oneHourBurnRate' | 'oneDayBurnRate', + slo: SLODefinition +) { + const aggKeyToRangeMap = { + fiveMinuteBurnRate: getFiveMinuteRange, + oneHourBurnRate: getOneHourRange, + oneDayBurnRate: getOneDayRange, + }; + + return { + [aggKey]: { + filter: { + range: { + '@timestamp': aggKeyToRangeMap[aggKey](slo), + }, + }, + ...(occurrencesBudgetingMethodSchema.is(slo.budgetingMethod) && { + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }), + ...(timeslicesBudgetingMethodSchema.is(slo.budgetingMethod) && { + aggs: { + goodEvents: { + sum: { + field: 'slo.isGoodSlice', + }, + }, + totalEvents: { + value_count: { + field: 'slo.isGoodSlice', + }, + }, + }, + }), + }, + }; +} diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts index fc2fdc6f22f2e..c473ed184f40c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_transform_generator/helpers/create_temp_summary.ts @@ -63,6 +63,22 @@ export interface EsSummaryDocument { kibanaUrl?: string; // >= 8.14 summaryUpdatedAt: string | null; latestSliTimestamp: string | null; + // >= 8.15 + fiveMinuteBurnRate?: { + totalEvents: number; + goodEvents: number; + value: number; + }; + oneHourBurnRate?: { + totalEvents: number; + goodEvents: number; + value: number; + }; + oneDayBurnRate?: { + totalEvents: number; + goodEvents: number; + value: number; + }; } export function createTempSummaryDocument( @@ -131,6 +147,22 @@ export function createTempSummaryDocument( kibanaUrl: basePath.publicBaseUrl ?? '', // added in 8.14, i.e. might be undefined summaryUpdatedAt: null, latestSliTimestamp: null, + // Added in 8.15 + fiveMinuteBurnRate: { + totalEvents: 0, + goodEvents: 0, + value: 0, + }, + oneHourBurnRate: { + totalEvents: 0, + goodEvents: 0, + value: 0, + }, + oneDayBurnRate: { + totalEvents: 0, + goodEvents: 0, + value: 0, + }, }; return doc; diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap index e3d9de62d62ce..dcb36e3ac06dd 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap @@ -400,13 +400,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -571,13 +571,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -742,13 +742,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap index c5021f57229f0..53af7ad5777ce 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap @@ -376,13 +376,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -534,13 +534,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -692,13 +692,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap index f9015e64984d9..c0dae33244b3d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/histogram.test.ts.snap @@ -77,13 +77,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -229,13 +229,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -381,13 +381,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap index b85642d631f26..4f5b239e982cf 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/kql_custom.test.ts.snap @@ -118,13 +118,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -243,13 +243,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -368,13 +368,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap index e123f9cf28ba6..351c4d57b8c5c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/metric_custom.test.ts.snap @@ -117,13 +117,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -280,13 +280,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap index 91c884611700f..6ee25d4927910 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/__snapshots__/timeslice_metric.test.ts.snap @@ -33,13 +33,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { @@ -247,13 +247,13 @@ Object { "_meta": Object { "managed": true, "managed_by": "observability", - "version": 3.2, + "version": 3.3, }, "defer_validation": true, "description": "Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]", "dest": Object { - "index": ".slo-observability.sli-v3.2", - "pipeline": ".slo-observability.sli.pipeline-v3.2", + "index": ".slo-observability.sli-v3.3", + "pipeline": ".slo-observability.sli.pipeline-v3.3", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/synthetics_availability.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/synthetics_availability.test.ts index b292b8d12f342..f59c1fd9a96e6 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_generators/synthetics_availability.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_generators/synthetics_availability.test.ts @@ -26,13 +26,13 @@ describe('Synthetics Availability Transform Generator', () => { _meta: { managed: true, managed_by: 'observability', - version: 3.2, + version: 3.3, }, defer_validation: true, description: 'Rolled-up SLI data for SLO: irrelevant [id: irrelevant, revision: 1]', dest: { - index: '.slo-observability.sli-v3.2', - pipeline: '.slo-observability.sli.pipeline-v3.2', + index: '.slo-observability.sli-v3.3', + pipeline: '.slo-observability.sli.pipeline-v3.3', }, frequency: '1m', pivot: { diff --git a/x-pack/test/api_integration/apis/slos/create_slo.ts b/x-pack/test/api_integration/apis/slos/create_slo.ts index 72735e7f668bb..f6fa12fe3d8ba 100644 --- a/x-pack/test/api_integration/apis/slos/create_slo.ts +++ b/x-pack/test/api_integration/apis/slos/create_slo.ts @@ -151,8 +151,8 @@ export default function ({ getService }: FtrProviderContext) { }, }, dest: { - index: '.slo-observability.sli-v3.2', - pipeline: '.slo-observability.sli.pipeline-v3.2', + index: '.slo-observability.sli-v3.3', + pipeline: '.slo-observability.sli.pipeline-v3.3', }, frequency: '1m', sync: { time: { field: '@timestamp', delay: '1m' } }, @@ -184,7 +184,7 @@ export default function ({ getService }: FtrProviderContext) { }, description: `Rolled-up SLI data for SLO: Test SLO for api integration [id: ${id}, revision: 1]`, settings: { deduce_mappings: false, unattended: true }, - _meta: { version: 3.2, managed: true, managed_by: 'observability' }, + _meta: { version: 3.3, managed: true, managed_by: 'observability' }, }, ], }); @@ -206,7 +206,7 @@ export default function ({ getService }: FtrProviderContext) { version: '10.0.0', create_time: summaryTransform.body.transforms[0].create_time, source: { - index: ['.slo-observability.sli-v3.2*'], + index: ['.slo-observability.sli-v3.3*'], query: { bool: { filter: [ @@ -218,7 +218,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, dest: { - index: '.slo-observability.summary-v3.2', + index: '.slo-observability.summary-v3.3', pipeline: `.slo-observability.summary.pipeline-${id}-1`, }, frequency: '1m', @@ -302,11 +302,77 @@ export default function ({ getService }: FtrProviderContext) { }, }, latestSliTimestamp: { max: { field: '@timestamp' } }, + fiveMinuteBurnRate: { + filter: { + range: { + '@timestamp': { + gte: 'now-480s/m', + lte: 'now-180s/m', + }, + }, + }, + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }, + oneHourBurnRate: { + filter: { + range: { + '@timestamp': { + gte: 'now-3780s/m', + lte: 'now-180s/m', + }, + }, + }, + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }, + oneDayBurnRate: { + filter: { + range: { + '@timestamp': { + gte: 'now-86580s/m', + lte: 'now-180s/m', + }, + }, + }, + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }, }, }, description: `Summarise the rollup data of SLO: Test SLO for api integration [id: ${id}, revision: 1].`, settings: { deduce_mappings: false, unattended: true }, - _meta: { version: 3.2, managed: true, managed_by: 'observability' }, + _meta: { version: 3.3, managed: true, managed_by: 'observability' }, }, ], }); diff --git a/x-pack/test/api_integration/apis/slos/update_slo.ts b/x-pack/test/api_integration/apis/slos/update_slo.ts index ebddd16c6508f..b8f4a14654d4d 100644 --- a/x-pack/test/api_integration/apis/slos/update_slo.ts +++ b/x-pack/test/api_integration/apis/slos/update_slo.ts @@ -155,8 +155,8 @@ export default function ({ getService }: FtrProviderContext) { }, }, dest: { - index: '.slo-observability.sli-v3.2', - pipeline: '.slo-observability.sli.pipeline-v3.2', + index: '.slo-observability.sli-v3.3', + pipeline: '.slo-observability.sli.pipeline-v3.3', }, frequency: '1m', sync: { time: { field: '@timestamp', delay: '1m' } }, @@ -188,7 +188,7 @@ export default function ({ getService }: FtrProviderContext) { }, description: `Rolled-up SLI data for SLO: Test SLO for api integration [id: ${id}, revision: 2]`, settings: { deduce_mappings: false, unattended: true }, - _meta: { version: 3.2, managed: true, managed_by: 'observability' }, + _meta: { version: 3.3, managed: true, managed_by: 'observability' }, }, ], }); @@ -210,7 +210,7 @@ export default function ({ getService }: FtrProviderContext) { version: '10.0.0', create_time: summaryTransform.body.transforms[0].create_time, source: { - index: ['.slo-observability.sli-v3.2*'], + index: ['.slo-observability.sli-v3.3*'], query: { bool: { filter: [ @@ -222,7 +222,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, dest: { - index: '.slo-observability.summary-v3.2', + index: '.slo-observability.summary-v3.3', pipeline: `.slo-observability.summary.pipeline-${id}-2`, }, frequency: '1m', @@ -306,11 +306,77 @@ export default function ({ getService }: FtrProviderContext) { }, }, latestSliTimestamp: { max: { field: '@timestamp' } }, + fiveMinuteBurnRate: { + filter: { + range: { + '@timestamp': { + gte: 'now-480s/m', + lte: 'now-180s/m', + }, + }, + }, + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }, + oneHourBurnRate: { + filter: { + range: { + '@timestamp': { + gte: 'now-3780s/m', + lte: 'now-180s/m', + }, + }, + }, + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }, + oneDayBurnRate: { + filter: { + range: { + '@timestamp': { + gte: 'now-86580s/m', + lte: 'now-180s/m', + }, + }, + }, + aggs: { + goodEvents: { + sum: { + field: 'slo.numerator', + }, + }, + totalEvents: { + sum: { + field: 'slo.denominator', + }, + }, + }, + }, }, }, description: `Summarise the rollup data of SLO: Test SLO for api integration [id: ${id}, revision: 2].`, settings: { deduce_mappings: false, unattended: true }, - _meta: { version: 3.2, managed: true, managed_by: 'observability' }, + _meta: { version: 3.3, managed: true, managed_by: 'observability' }, }, ], }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/create_slo.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/create_slo.ts index 02ac42ad6e81a..197d68bdaa77f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/slos/create_slo.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/create_slo.ts @@ -149,10 +149,10 @@ export default function ({ getService }: FtrProviderContext) { const expectedTransforms: ExpectedTransforms = { count: 2, results: { - transform0: { id: 'slo-my-custom-id1-1', destIndex: '.slo-observability.sli-v3.2' }, + transform0: { id: 'slo-my-custom-id1-1', destIndex: '.slo-observability.sli-v3.3' }, transform1: { id: 'slo-summary-my-custom-id1-1', - destIndex: '.slo-observability.summary-v3.2', + destIndex: '.slo-observability.summary-v3.3', }, }, typeOfVersion: 'string', @@ -318,25 +318,25 @@ export default function ({ getService }: FtrProviderContext) { const expectedTransforms: ExpectedTransforms = { count: 8, results: { - transform0: { id: 'slo-my-custom-id1-1', destIndex: '.slo-observability.sli-v3.2' }, - transform1: { id: 'slo-my-custom-id2-1', destIndex: '.slo-observability.sli-v3.2' }, - transform2: { id: 'slo-my-custom-id3-1', destIndex: '.slo-observability.sli-v3.2' }, - transform3: { id: 'slo-my-custom-id4-1', destIndex: '.slo-observability.sli-v3.2' }, + transform0: { id: 'slo-my-custom-id1-1', destIndex: '.slo-observability.sli-v3.3' }, + transform1: { id: 'slo-my-custom-id2-1', destIndex: '.slo-observability.sli-v3.3' }, + transform2: { id: 'slo-my-custom-id3-1', destIndex: '.slo-observability.sli-v3.3' }, + transform3: { id: 'slo-my-custom-id4-1', destIndex: '.slo-observability.sli-v3.3' }, transform4: { id: 'slo-summary-my-custom-id1-1', - destIndex: '.slo-observability.summary-v3.2', + destIndex: '.slo-observability.summary-v3.3', }, transform5: { id: 'slo-summary-my-custom-id2-1', - destIndex: '.slo-observability.summary-v3.2', + destIndex: '.slo-observability.summary-v3.3', }, transform6: { id: 'slo-summary-my-custom-id3-1', - destIndex: '.slo-observability.summary-v3.2', + destIndex: '.slo-observability.summary-v3.3', }, transform7: { id: 'slo-summary-my-custom-id4-1', - destIndex: '.slo-observability.summary-v3.2', + destIndex: '.slo-observability.summary-v3.3', }, }, typeOfVersion: 'string', From d243e4f28e484f28bad5eef073d2f469d21a19d4 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 17 Jun 2024 17:43:28 +0200 Subject: [PATCH 016/127] [ES|QL] Moves the @timestamp assignment to the ESQL util (#186158) ## Summary This PR just moves the @timestamp assignment logic from the various consumers to the helper function. It is much cleaner that way and I want to add support of the named parameters so I want to have a central function to accomplish this https://github.com/elastic/kibana/issues/180805 --- .../src/utils/get_esql_adhoc_dataview.ts | 10 +++++++++- .../main/state_management/utils/get_esql_data_view.ts | 9 +-------- .../requests/get_data_view_by_index_pattern.ts | 10 ++-------- .../app_plugin/shared/edit_on_the_fly/helpers.ts | 4 ---- .../lens/public/datasources/text_based/utils.ts | 3 --- .../public/functions/visualize_esql.tsx | 7 +------ 6 files changed, 13 insertions(+), 30 deletions(-) diff --git a/packages/kbn-esql-utils/src/utils/get_esql_adhoc_dataview.ts b/packages/kbn-esql-utils/src/utils/get_esql_adhoc_dataview.ts index e1e599946ef59..b05dfbe5f5788 100644 --- a/packages/kbn-esql-utils/src/utils/get_esql_adhoc_dataview.ts +++ b/packages/kbn-esql-utils/src/utils/get_esql_adhoc_dataview.ts @@ -31,11 +31,19 @@ export async function getESQLAdHocDataview( indexPattern: string, dataViewsService: DataViewsPublicPluginStart ) { - return await dataViewsService.create({ + const dataView = await dataViewsService.create({ title: indexPattern, type: ESQL_TYPE, id: await sha256(`esql-${indexPattern}`), }); + + // If the indexPattern is empty string means that the user used either the ROW or META FUNCTIONS / SHOW INFO commands + // we don't want to add the @timestamp field in this case https://github.com/elastic/kibana/issues/163417 + if (indexPattern && dataView?.fields?.getByName?.('@timestamp')?.type === 'date') { + dataView.timeFieldName = '@timestamp'; + } + + return dataView; } /** diff --git a/src/plugins/discover/public/application/main/state_management/utils/get_esql_data_view.ts b/src/plugins/discover/public/application/main/state_management/utils/get_esql_data_view.ts index c4dd4d7e163b8..7f30ced5be035 100644 --- a/src/plugins/discover/public/application/main/state_management/utils/get_esql_data_view.ts +++ b/src/plugins/discover/public/application/main/state_management/utils/get_esql_data_view.ts @@ -21,14 +21,7 @@ export async function getEsqlDataView( currentDataView?.isPersisted() || indexPatternFromQuery !== currentDataView?.getIndexPattern() ) { - const dataViewObj = await getESQLAdHocDataview(indexPatternFromQuery, services.dataViews); - - // If the indexPatternFromQuery is empty string means that the user used either the ROW or SHOW META / SHOW INFO commands - // we don't want to add the @timestamp field in this case https://github.com/elastic/kibana/issues/163417 - if (indexPatternFromQuery && dataViewObj.fields.getByName('@timestamp')?.type === 'date') { - dataViewObj.timeFieldName = '@timestamp'; - } - return dataViewObj; + return await getESQLAdHocDataview(indexPatternFromQuery, services.dataViews); } return currentDataView; } diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_data_view_by_index_pattern.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_data_view_by_index_pattern.ts index 8d0385e8d9f9e..8ef09d59555ea 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_data_view_by_index_pattern.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_data_view_by_index_pattern.ts @@ -6,6 +6,7 @@ */ import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; +import { getESQLAdHocDataview } from '@kbn/esql-utils'; /** * Get a saved data view that matches the index pattern (as close as possible) @@ -34,14 +35,7 @@ export async function getOrCreateDataViewByIndexPattern( indexPatternFromQuery && (currentDataView?.isPersisted() || indexPatternFromQuery !== currentDataView?.getIndexPattern()) ) { - const dataViewObj = await dataViews.create({ - title: indexPatternFromQuery, - }); - - if (dataViewObj.fields.getByName('@timestamp')?.type === 'date') { - dataViewObj.timeFieldName = '@timestamp'; - } - return dataViewObj; + return await getESQLAdHocDataview(indexPatternFromQuery, dataViews); } return currentDataView; } diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts index d1dd5febca59e..8da4c87607987 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts @@ -36,10 +36,6 @@ export const getSuggestions = async ( ? await deps.dataViews.create(dataViewSpec) : await getESQLAdHocDataview(indexPattern, deps.dataViews); - if (dataView.fields.getByName('@timestamp')?.type === 'date' && !dataViewSpec) { - dataView.timeFieldName = '@timestamp'; - } - const columns = await getESQLQueryColumns({ esqlQuery: 'esql' in query ? query.esql : '', search: deps.data.search.search, diff --git a/x-pack/plugins/lens/public/datasources/text_based/utils.ts b/x-pack/plugins/lens/public/datasources/text_based/utils.ts index 4ca9324df6fc4..9621ab8103e4a 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/utils.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/utils.ts @@ -88,9 +88,6 @@ export async function getStateFromAggregateQuery( const dataView = await getESQLAdHocDataview(indexPattern, dataViews); if (dataView && dataView.id) { - if (dataView?.fields?.getByName('@timestamp')?.type === 'date') { - dataView.timeFieldName = '@timestamp'; - } dataViewId = dataView?.id; indexPatternRefs = [ ...indexPatternRefs, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/functions/visualize_esql.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/functions/visualize_esql.tsx index 97c46a6a2d759..9442a73751628 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/functions/visualize_esql.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/functions/visualize_esql.tsx @@ -124,12 +124,7 @@ export function VisualizeESQL({ }, [lens]); const dataViewAsync = useAsync(() => { - return getESQLAdHocDataview(indexPattern, dataViews).then((dataView) => { - if (dataView.fields.getByName('@timestamp')?.type === 'date') { - dataView.timeFieldName = '@timestamp'; - } - return dataView; - }); + return getESQLAdHocDataview(indexPattern, dataViews); }, [indexPattern, dataViews]); const chatFlyoutSecondSlotHandler = useContext(ObservabilityAIAssistantMultipaneFlyoutContext); From e78c7228e35f7a9983d060c726c7581c64ff374c Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Mon, 17 Jun 2024 17:56:29 +0200 Subject: [PATCH 017/127] [Discover][Extension] Document Viewer (#185940) - Closes https://github.com/elastic/kibana/issues/184084 ## Summary This PR adds extension points to Doc Viewer flyout: - `title` - `docViewsRegistry`. Example: ```typescript profile: { getDocViewer: (prev) => (params) => { const recordId = params.record.id; const prevValue = prev(params); return { title: `${prevValue.title} #${recordId}`, docViewsRegistry: (registry) => { registry.enableById('doc_view_logs_overview'); return prevValue.docViewsRegistry(registry); }, }; }, }, ``` ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../discover_grid_flyout.test.tsx | 97 +++++++++++++------ .../discover_grid_flyout.tsx | 40 +++++--- .../context_awareness/__mocks__/index.ts | 18 ++++ .../public/context_awareness/types.ts | 12 +++ 4 files changed, 126 insertions(+), 41 deletions(-) diff --git a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx index cb02e3b736663..456f10d89dc89 100644 --- a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx +++ b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx @@ -19,7 +19,7 @@ import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefi import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataTableRecord, EsHitRecord } from '@kbn/discover-utils/types'; -import { buildDataTableRecord } from '@kbn/discover-utils'; +import { buildDataTableRecord, buildDataTableRecordList } from '@kbn/discover-utils'; import { act } from 'react-dom/test-utils'; import { ReactWrapper } from 'enzyme'; import { setUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/plugin'; @@ -64,19 +64,8 @@ const waitNextUpdate = async (component: ReactWrapper) => { }; describe('Discover flyout', function () { - const mountComponent = async ({ - dataView, - hits, - hitIndex, - query, - }: { - dataView?: DataView; - hits?: DataTableRecord[]; - hitIndex?: number; - query?: Query | AggregateQuery; - }) => { - const onClose = jest.fn(); - const services = { + const getServices = () => { + return { ...discoverServiceMock, filterManager: createFilterManagerMock(), addBasePath: (path: string) => `/base${path}`, @@ -92,22 +81,35 @@ describe('Discover flyout', function () { addSuccess: jest.fn(), }, } as unknown as DiscoverServices; + }; + + const mountComponent = async ({ + dataView, + records, + expandedHit, + query, + services = getServices(), + }: { + dataView?: DataView; + records?: DataTableRecord[]; + expandedHit?: EsHitRecord; + query?: Query | AggregateQuery; + services?: DiscoverServices; + }) => { + const onClose = jest.fn(); setUnifiedDocViewerServices(mockUnifiedDocViewerServices); - const hit = buildDataTableRecord( - hitIndex ? esHitsMock[hitIndex] : (esHitsMock[0] as EsHitRecord), - dataViewMock - ); + const currentRecords = + records || + esHitsMock.map((entry: EsHitRecord) => buildDataTableRecord(entry, dataView || dataViewMock)); const props = { columns: ['date'], dataView: dataView || dataViewMock, - hit, - hits: - hits || - esHitsMock.map((entry: EsHitRecord) => - buildDataTableRecord(entry, dataView || dataViewMock) - ), + hit: expandedHit + ? buildDataTableRecord(expandedHit, dataView || dataViewMock) + : currentRecords[0], + hits: currentRecords, query, onAddColumn: jest.fn(), onClose, @@ -131,6 +133,7 @@ describe('Discover flyout', function () { beforeEach(() => { mockFlyoutCustomization.actions.defaultActions = undefined; mockFlyoutCustomization.Content = undefined; + mockFlyoutCustomization.title = undefined; jest.clearAllMocks(); (useDiscoverCustomization as jest.Mock).mockImplementation(() => mockFlyoutCustomization); @@ -163,14 +166,14 @@ describe('Discover flyout', function () { }); it('displays no document navigation when there are 0 docs available', async () => { - const { component } = await mountComponent({ hits: [] }); + const { component } = await mountComponent({ records: [], expandedHit: esHitsMock[0] }); const docNav = findTestSubject(component, 'dscDocNavigation'); expect(docNav.length).toBeFalsy(); }); it('displays no document navigation when the expanded doc is not part of the given docs', async () => { // scenario: you've expanded a doc, and in the next request differed docs where fetched - const hits = [ + const records = [ { _index: 'new', _id: '1', @@ -186,7 +189,7 @@ describe('Discover flyout', function () { _source: { date: '2020-20-01T12:12:12.124', name: 'test2', extension: 'jpg' }, }, ].map((hit) => buildDataTableRecord(hit, dataViewMock)); - const { component } = await mountComponent({ hits }); + const { component } = await mountComponent({ records, expandedHit: esHitsMock[0] }); const docNav = findTestSubject(component, 'dscDocNavigation'); expect(docNav.length).toBeFalsy(); }); @@ -208,14 +211,18 @@ describe('Discover flyout', function () { it('doesnt allow you to navigate to the next doc, if expanded doc is the last', async () => { // scenario: you've expanded a doc, and in the next request differed docs where fetched - const { component, props } = await mountComponent({ hitIndex: esHitsMock.length - 1 }); + const { component, props } = await mountComponent({ + expandedHit: esHitsMock[esHitsMock.length - 1], + }); findTestSubject(component, 'pagination-button-next').simulate('click'); expect(props.setExpandedDoc).toHaveBeenCalledTimes(0); }); it('allows you to navigate to the previous doc, if expanded doc is the last', async () => { // scenario: you've expanded a doc, and in the next request differed docs where fetched - const { component, props } = await mountComponent({ hitIndex: esHitsMock.length - 1 }); + const { component, props } = await mountComponent({ + expandedHit: esHitsMock[esHitsMock.length - 1], + }); findTestSubject(component, 'pagination-button-previous').simulate('click'); expect(props.setExpandedDoc).toHaveBeenCalledTimes(1); expect(props.setExpandedDoc.mock.calls[0][0].raw._id).toBe('4'); @@ -470,5 +477,37 @@ describe('Discover flyout', function () { expect(props.onFilter).toHaveBeenCalled(); }); }); + + describe('context awareness', () => { + it('should render flyout per the defined document profile', async () => { + const services = getServices(); + const hits = [ + { + _index: 'new', + _id: '1', + _score: 1, + _type: '_doc', + _source: { date: '2020-20-01T12:12:12.123', message: 'test1', bytes: 20 }, + }, + { + _index: 'new', + _id: '2', + _score: 1, + _type: '_doc', + _source: { date: '2020-20-01T12:12:12.124', name: 'test2', extension: 'jpg' }, + }, + ]; + const records = buildDataTableRecordList({ + records: hits as EsHitRecord[], + dataView: dataViewMock, + processRecord: (record) => services.profilesManager.resolveDocumentProfile({ record }), + }); + const { component } = await mountComponent({ records, services }); + const title = findTestSubject(component, 'docTableRowDetailsTitle'); + expect(title.text()).toBe('Document #new::1::'); + const content = findTestSubject(component, 'kbnDocViewer'); + expect(content.text()).toBe('Mock tab'); + }); + }); }); }); diff --git a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx index d6273d7669391..891ae384bd41a 100644 --- a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx +++ b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx @@ -31,12 +31,14 @@ import { Filter, Query, AggregateQuery, isOfAggregateQueryType } from '@kbn/es-q import type { DataTableRecord } from '@kbn/discover-utils/types'; import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import type { DataTableColumnsMeta } from '@kbn/unified-data-table'; +import type { DocViewsRegistry } from '@kbn/unified-doc-viewer'; import { UnifiedDocViewer } from '@kbn/unified-doc-viewer-plugin/public'; import useLocalStorage from 'react-use/lib/useLocalStorage'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import { useFlyoutActions } from './use_flyout_actions'; import { useDiscoverCustomization } from '../../customizations'; import { DiscoverGridFlyoutActions } from './discover_grid_flyout_actions'; +import { useProfileAccessor } from '../../context_awareness'; export interface DiscoverGridFlyoutProps { savedSearchId?: string; @@ -161,6 +163,29 @@ export function DiscoverGridFlyout({ [onRemoveColumn, services.toastNotifications] ); + const defaultFlyoutTitle = isEsqlQuery + ? i18n.translate('discover.grid.tableRow.docViewerEsqlDetailHeading', { + defaultMessage: 'Result', + }) + : i18n.translate('discover.grid.tableRow.docViewerDetailHeading', { + defaultMessage: 'Document', + }); + + const getDocViewerAccessor = useProfileAccessor('getDocViewer', { + record: actualHit, + }); + const docViewer = useMemo(() => { + const getDocViewer = getDocViewerAccessor(() => ({ + title: flyoutCustomization?.title ?? defaultFlyoutTitle, + docViewsRegistry: (registry: DocViewsRegistry) => + typeof flyoutCustomization?.docViewsRegistry === 'function' + ? flyoutCustomization.docViewsRegistry(registry) + : registry, + })); + + return getDocViewer({ record: actualHit }); + }, [defaultFlyoutTitle, flyoutCustomization, getDocViewerAccessor, actualHit]); + const renderDefaultContent = useCallback( () => ( ), [ @@ -185,7 +210,7 @@ export function DiscoverGridFlyout({ isEsqlQuery, onFilter, removeColumn, - flyoutCustomization?.docViewsRegistry, + docViewer.docViewsRegistry, ] ); @@ -208,15 +233,6 @@ export function DiscoverGridFlyout({ renderDefaultContent() ); - const defaultFlyoutTitle = isEsqlQuery - ? i18n.translate('discover.grid.tableRow.docViewerEsqlDetailHeading', { - defaultMessage: 'Result', - }) - : i18n.translate('discover.grid.tableRow.docViewerDetailHeading', { - defaultMessage: 'Document', - }); - const flyoutTitle = flyoutCustomization?.title ?? defaultFlyoutTitle; - return ( -

{flyoutTitle}

+

{docViewer.title}

{activePage !== -1 && ( diff --git a/src/plugins/discover/public/context_awareness/__mocks__/index.ts b/src/plugins/discover/public/context_awareness/__mocks__/index.ts index 0f8beed5d955f..b493ff43bfbca 100644 --- a/src/plugins/discover/public/context_awareness/__mocks__/index.ts +++ b/src/plugins/discover/public/context_awareness/__mocks__/index.ts @@ -61,6 +61,24 @@ export const createContextAwarenessMocks = () => { ...prev(), rootProfile: () => 'document-profile', })), + getDocViewer: (prev) => (params) => { + const recordId = params.record.id; + const prevValue = prev(params); + return { + title: `${prevValue.title} #${recordId}`, + docViewsRegistry: (registry) => { + registry.add({ + id: 'doc_view_mock', + title: 'Mock tab', + order: 10, + component: () => { + return null; + }, + }); + return prevValue.docViewsRegistry(registry); + }, + }; + }, } as DocumentProfileProvider['profile'], resolve: jest.fn(() => ({ isMatch: true, diff --git a/src/plugins/discover/public/context_awareness/types.ts b/src/plugins/discover/public/context_awareness/types.ts index b612b2ce29907..4bc75e6e1727d 100644 --- a/src/plugins/discover/public/context_awareness/types.ts +++ b/src/plugins/discover/public/context_awareness/types.ts @@ -7,7 +7,19 @@ */ import type { CustomCellRenderer } from '@kbn/unified-data-table'; +import type { DocViewsRegistry } from '@kbn/unified-doc-viewer'; +import type { DataTableRecord } from '@kbn/discover-utils'; + +export interface DocViewerExtension { + title: string; + docViewsRegistry: (prevRegistry: DocViewsRegistry) => DocViewsRegistry; +} + +export interface DocViewerExtensionParams { + record: DataTableRecord; +} export interface Profile { getCellRenderers: () => CustomCellRenderer; + getDocViewer: (params: DocViewerExtensionParams) => DocViewerExtension; } From 934a4f0edc8f7d97a64147528dbf79d7c0a9ae24 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Mon, 17 Jun 2024 09:39:01 -0700 Subject: [PATCH 018/127] [OAS] Refresh data views API document (#186059) --- src/plugins/data_views/docs/openapi/README.md | 9 +- .../data_views/docs/openapi/bundled.json | 944 +++++++++++++++--- .../data_views/docs/openapi/bundled.yaml | 518 +++++++++- .../components/parameters/space_id.yaml | 3 +- .../data_views/docs/openapi/entrypoint.yaml | 70 +- .../docs/openapi/paths/api@data_views.yaml | 41 + .../paths/api@data_views@data_view.yaml | 31 + .../api@data_views@data_view@{viewid}.yaml | 79 ++ ...@data_views@data_view@{viewid}@fields.yaml | 42 + ...iews@data_view@{viewid}@runtime_field.yaml | 99 ++ ...ew@{viewid}@runtime_field@{fieldname}.yaml | 94 ++ .../openapi/paths/api@data_views@default.yaml | 74 ++ .../paths/s@{spaceid}@api@data_views.yaml | 2 +- .../s@{spaceid}@api@data_views@data_view.yaml | 2 +- ...id}@api@data_views@data_view@{viewid}.yaml | 6 +- ...@data_views@data_view@{viewid}@fields.yaml | 3 +- ...iews@data_view@{viewid}@runtime_field.yaml | 17 +- ...ew@{viewid}@runtime_field@{fieldname}.yaml | 6 +- .../s@{spaceid}@api@data_views@default.yaml | 7 +- 19 files changed, 1837 insertions(+), 210 deletions(-) create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views.yaml create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml create mode 100644 src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml diff --git a/src/plugins/data_views/docs/openapi/README.md b/src/plugins/data_views/docs/openapi/README.md index 1480da8537706..dd871a82de129 100644 --- a/src/plugins/data_views/docs/openapi/README.md +++ b/src/plugins/data_views/docs/openapi/README.md @@ -14,14 +14,7 @@ A guide about the openApi specification can be found at [https://swagger.io/docs ## Tools -It is possible to validate the docs before bundling them with the following -command: - -```bash -npx swagger-cli validate entrypoint.yaml -``` - -Then you can generate the `bundled` files by running the following commands: +Generate the `bundled` files by running the following commands: ```bash npx @redocly/cli bundle entrypoint.yaml --output bundled.yaml --ext yaml diff --git a/src/plugins/data_views/docs/openapi/bundled.json b/src/plugins/data_views/docs/openapi/bundled.json index 3b435603f7d34..28893b86cef3f 100644 --- a/src/plugins/data_views/docs/openapi/bundled.json +++ b/src/plugins/data_views/docs/openapi/bundled.json @@ -1,5 +1,5 @@ { - "openapi": "3.1.0", + "openapi": "3.0.3", "info": { "title": "Data views", "description": "OpenAPI schema for data view endpoints", @@ -14,7 +14,12 @@ }, "servers": [ { - "url": "/" + "url": "https://{kibana_url}", + "variables": { + "kibana_url": { + "default": "localhost:5601" + } + } } ], "security": [ @@ -34,7 +39,7 @@ "paths": { "/s/{spaceId}/api/data_views": { "get": { - "summary": "Retrieves a list of all data views.", + "summary": "Get all data views", "operationId": "getAllDataViews", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ @@ -104,7 +109,7 @@ }, "/s/{spaceId}/api/data_views/data_view": { "post": { - "summary": "Creates a data view.", + "summary": "Create a data view", "operationId": "createDataView", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ @@ -159,7 +164,7 @@ }, "/s/{spaceId}/api/data_views/data_view/{viewId}": { "get": { - "summary": "Retrieves a single data view by identifier.", + "summary": "Get a data view", "operationId": "getDataView", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ @@ -202,7 +207,7 @@ } }, "delete": { - "summary": "Deletes a data view.", + "summary": "Delete a data view", "operationId": "deleteDataView", "description": "WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ @@ -223,21 +228,636 @@ "204": { "description": "Indicates a successful call." }, - "404": { - "description": "Object is not found.", + "404": { + "description": "Object is not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/404_response" + } + } + } + } + } + }, + "post": { + "summary": "Update a data view", + "operationId": "updateDataView", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/view_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/update_data_view_request_object" + }, + "examples": { + "updateDataViewRequest": { + "$ref": "#/components/examples/update_data_view_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/data_view_response_object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + } + }, + "/s/{spaceId}/api/data_views/default": { + "get": { + "summary": "Get the default data view identifier", + "operationId": "getDefaultDataView", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/space_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data_view_id": { + "type": "string" + } + } + }, + "examples": { + "getDefaultDataViewResponse": { + "$ref": "#/components/examples/get_default_data_view_response" + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + }, + "post": { + "summary": "Sets the default data view identifier", + "operationId": "setDefaultDatailView", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data_view_id" + ], + "properties": { + "data_view_id": { + "type": "string", + "nullable": true, + "description": "The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view.\n" + }, + "force": { + "type": "boolean", + "description": "Update an existing default data view identifier.", + "default": false + } + } + }, + "examples": { + "setDefaultDataViewRequest": { + "$ref": "#/components/examples/set_default_data_view_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "acknowledged": { + "type": "boolean" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + } + }, + "/s/{spaceId}/api/data_views/data_view/{viewId}/fields": { + "post": { + "summary": "Update data view fields metadata", + "operationId": "updateFieldsMetadata", + "description": "Update fields presentation metadata such as count, customLabel and format. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/view_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "fields" + ], + "properties": { + "fields": { + "description": "The field object.", + "type": "object" + } + } + }, + "examples": { + "updateFieldsMetadataRequest": { + "$ref": "#/components/examples/update_field_metadata_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "acknowledged": { + "type": "boolean" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + } + }, + "/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field": { + "post": { + "summary": "Create a runtime field", + "operationId": "createRuntimeField", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/view_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "runtimeField" + ], + "properties": { + "name": { + "type": "string", + "description": "The name for a runtime field.\n" + }, + "runtimeField": { + "type": "object", + "description": "The runtime field definition object.\n" + } + } + }, + "examples": { + "createRuntimeFieldRequest": { + "$ref": "#/components/examples/create_runtime_field_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + } + }, + "put": { + "summary": "Create or update a runtime field", + "operationId": "createUpdateRuntimeField", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/space_id" + }, + { + "name": "viewId", + "in": "path", + "description": "The ID of the data view fields you want to update.\n", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "runtimeField" + ], + "properties": { + "name": { + "type": "string", + "description": "The name for a runtime field.\n" + }, + "runtimeField": { + "type": "object", + "description": "The runtime field definition object.\n" + } + } + }, + "examples": { + "updateRuntimeFieldRequest": { + "$ref": "#/components/examples/create_runtime_field_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data_view": { + "type": "object" + }, + "fields": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + } + }, + "/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field/{fieldName}": { + "get": { + "summary": "Get a runtime field", + "operationId": "getRuntimeField", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/field_name" + }, + { + "$ref": "#/components/parameters/view_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data_view": { + "type": "object" + }, + "fields": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "examples": { + "getRuntimeFieldResponse": { + "$ref": "#/components/examples/get_runtime_field_response" + } + } + } + } + }, + "404": { + "description": "Object is not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/404_response" + } + } + } + } + } + }, + "delete": { + "summary": "Delete a runtime field from a data view", + "operationId": "deleteRuntimeField", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/field_name" + }, + { + "$ref": "#/components/parameters/view_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call." + }, + "404": { + "description": "Object is not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/404_response" + } + } + } + } + } + }, + "post": { + "summary": "Update a runtime field", + "operationId": "updateRuntimeField", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/field_name" + }, + { + "$ref": "#/components/parameters/view_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "runtimeField" + ], + "properties": { + "runtimeField": { + "type": "object", + "description": "The runtime field definition object.\n\nYou can update following fields:\n\n- `type`\n- `script`\n" + } + } + }, + "examples": { + "updateRuntimeFieldRequest": { + "$ref": "#/components/examples/update_runtime_field_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call." + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + } + }, + "/api/data_views": { + "get": { + "summary": "Get all data views in the default space", + "operationId": "getAllDataViewsDefault", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data_view": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespaces": { + "type": "array", + "items": { + "type": "string" + } + }, + "title": { + "type": "string" + }, + "typeMeta": { + "type": "object" + } + } + } + } + } + }, + "examples": { + "getAllDataViewsResponse": { + "$ref": "#/components/examples/get_data_views_response" + } + } + } + } + }, + "400": { + "description": "Bad request", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/404_response" + "$ref": "#/components/schemas/400_response" } } } } } - }, + } + }, + "/api/data_views/data_view": { "post": { - "summary": "Updates a data view.", - "operationId": "updateDataView", + "summary": "Create a data view in the default space", + "operationId": "createDataViewDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -245,12 +865,6 @@ "parameters": [ { "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "$ref": "#/components/parameters/view_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -258,11 +872,11 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/update_data_view_request_object" + "$ref": "#/components/schemas/create_data_view_request_object" }, "examples": { - "updateDataViewRequest": { - "$ref": "#/components/examples/update_data_view_request" + "createDataViewRequest": { + "$ref": "#/components/examples/create_data_view_request" } } } @@ -292,17 +906,17 @@ } } }, - "/s/{spaceId}/api/data_views/default": { + "/api/data_views/data_view/{viewId}": { "get": { - "summary": "Retrieves the default data view identifier.", - "operationId": "getDefaultDataView", + "summary": "Get a data view in the default space", + "operationId": "getDataViewDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], "parameters": [ { - "$ref": "#/components/parameters/space_id" + "$ref": "#/components/parameters/view_id" } ], "responses": { @@ -311,27 +925,53 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "data_view_id": { - "type": "string" - } - } + "$ref": "#/components/schemas/data_view_response_object" }, "examples": { - "getDefaultDataViewResponse": { - "$ref": "#/components/examples/get_default_data_view_response" + "getDataViewResponse": { + "$ref": "#/components/examples/get_data_view_response" } } } } }, - "400": { - "description": "Bad request", + "404": { + "description": "Object is not found.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/400_response" + "$ref": "#/components/schemas/404_response" + } + } + } + } + } + }, + "delete": { + "summary": "Delete a data view from the default space", + "operationId": "deleteDataViewDefault", + "description": "WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/view_id" + } + ], + "responses": { + "204": { + "description": "Indicates a successful call." + }, + "404": { + "description": "Object is not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/404_response" } } } @@ -339,8 +979,8 @@ } }, "post": { - "summary": "Sets the default data view identifier.", - "operationId": "setDefaultDatailView", + "summary": "Update a data view in the default space", + "operationId": "updateDataViewDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -350,7 +990,7 @@ "$ref": "#/components/parameters/kbn_xsrf" }, { - "$ref": "#/components/parameters/space_id" + "$ref": "#/components/parameters/view_id" } ], "requestBody": { @@ -358,28 +998,11 @@ "content": { "application/json": { "schema": { - "type": "object", - "required": [ - "data_view_id" - ], - "properties": { - "data_view_id": { - "type": [ - "string", - "null" - ], - "description": "The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view.\n" - }, - "force": { - "type": "boolean", - "description": "Update an existing default data view identifier.", - "default": false - } - } + "$ref": "#/components/schemas/update_data_view_request_object" }, "examples": { - "setDefaultDataViewRequest": { - "$ref": "#/components/examples/set_default_data_view_request" + "updateDataViewRequest": { + "$ref": "#/components/examples/update_data_view_request" } } } @@ -391,12 +1014,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "acknowledged": { - "type": "boolean" - } - } + "$ref": "#/components/schemas/data_view_response_object" } } } @@ -414,11 +1032,11 @@ } } }, - "/s/{spaceId}/api/data_views/data_view/{viewId}/fields": { + "/api/data_views/data_view/{viewId}/fields": { "post": { - "summary": "Update fields presentation metadata such as count, customLabel and format.", - "operationId": "updateFieldsMetadata", - "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value.\n", + "summary": "Update data view fields metadata in the default space", + "operationId": "updateFieldsMetadataDefault", + "description": "Update fields presentation metadata such as count, customLabel and format. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value.\n", "tags": [ "data views" ], @@ -428,9 +1046,6 @@ }, { "$ref": "#/components/parameters/view_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -486,10 +1101,10 @@ } } }, - "/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field": { + "/api/data_views/data_view/{viewId}/runtime_field": { "post": { - "summary": "Creates a runtime field.", - "operationId": "createRuntimeField", + "summary": "Create a runtime field in the default space", + "operationId": "createRuntimeFieldDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -500,9 +1115,6 @@ }, { "$ref": "#/components/parameters/view_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -533,11 +1145,23 @@ } } } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } } }, "put": { - "summary": "Create or update an existing runtime field.", - "operationId": "createUpdateRuntimeField", + "summary": "Create or update a runtime field in the default space", + "operationId": "createUpdateRuntimeFieldDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -546,9 +1170,6 @@ { "$ref": "#/components/parameters/kbn_xsrf" }, - { - "$ref": "#/components/parameters/space_id" - }, { "name": "viewId", "in": "path", @@ -606,11 +1227,6 @@ } } } - }, - "examples": { - "createRuntimeFieldResponse": { - "$ref": "#/components/examples/create_runtime_field_response" - } } } } @@ -628,10 +1244,10 @@ } } }, - "/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field/{fieldName}": { + "/api/data_views/data_view/{viewId}/runtime_field/{fieldName}": { "get": { - "summary": "Retrieves a runtime field.", - "operationId": "getRuntimeField", + "summary": "Get a runtime field in the default space", + "operationId": "getRuntimeFieldDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -642,9 +1258,6 @@ }, { "$ref": "#/components/parameters/view_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "responses": { @@ -687,8 +1300,8 @@ } }, "delete": { - "summary": "Delete a runtime field from a data view.", - "operationId": "deleteRuntimeField", + "summary": "Delete a runtime field from a data view in the default space", + "operationId": "deleteRuntimeFieldDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -699,9 +1312,6 @@ }, { "$ref": "#/components/parameters/view_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "responses": { @@ -721,8 +1331,8 @@ } }, "post": { - "summary": "Update an existing runtime field.", - "operationId": "updateRuntimeField", + "summary": "Update a runtime field in the default space", + "operationId": "updateRuntimeFieldDefault", "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" @@ -733,9 +1343,6 @@ }, { "$ref": "#/components/parameters/view_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -778,6 +1385,118 @@ } } } + }, + "/api/data_views/default": { + "get": { + "summary": "Get the default data view in the default space", + "operationId": "getDefaultDataViewDefault", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data_view_id": { + "type": "string" + } + } + }, + "examples": { + "getDefaultDataViewResponse": { + "$ref": "#/components/examples/get_default_data_view_response" + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + }, + "post": { + "summary": "Set the default data view in the default space", + "operationId": "setDefaultDatailViewDefault", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data_view_id" + ], + "properties": { + "data_view_id": { + "type": "string", + "nullable": true, + "description": "The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view.\n" + }, + "force": { + "type": "boolean", + "description": "Update an existing default data view identifier.", + "default": false + } + } + }, + "examples": { + "setDefaultDataViewRequest": { + "$ref": "#/components/examples/set_default_data_view_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "acknowledged": { + "type": "boolean" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + } + } } }, "components": { @@ -790,7 +1509,7 @@ "type": "apiKey", "in": "header", "name": "Authorization", - "description": "e.g. Authorization: ApiKey base64AccessApiKey" + "description": "Serverless APIs support only key-based authentication. You must create an API key and use the encoded value in the request header. For example: 'Authorization: ApiKey base64AccessApiKey'.\n" } }, "parameters": { @@ -801,9 +1520,7 @@ "required": true, "schema": { "type": "string", - "examples": [ - "default" - ] + "example": "default" } }, "kbn_xsrf": { @@ -2090,17 +2807,6 @@ } } }, - "create_runtime_field_response": { - "summary": "The API returns created runtime field object array and updated data view object.", - "value": { - "data_view": { - "...": null - }, - "fields": [ - "..." - ] - } - }, "get_runtime_field_response": { "summary": "The get runtime field API returns a JSON object that contains information about the runtime field (`hour_of_day`) and the data view (`d3d7af60-4c81-11e8-b3d7-01146121b73d`).", "value": { diff --git a/src/plugins/data_views/docs/openapi/bundled.yaml b/src/plugins/data_views/docs/openapi/bundled.yaml index 5f8ce9d8c18f7..dee19e6b1d67b 100644 --- a/src/plugins/data_views/docs/openapi/bundled.yaml +++ b/src/plugins/data_views/docs/openapi/bundled.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Data views description: OpenAPI schema for data view endpoints @@ -9,7 +9,10 @@ info: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license servers: - - url: / + - url: https://{kibana_url} + variables: + kibana_url: + default: localhost:5601 security: - basicAuth: [] - apiKeyAuth: [] @@ -19,7 +22,7 @@ tags: paths: /s/{spaceId}/api/data_views: get: - summary: Retrieves a list of all data views. + summary: Get all data views operationId: getAllDataViews description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -63,7 +66,7 @@ paths: $ref: '#/components/schemas/400_response' /s/{spaceId}/api/data_views/data_view: post: - summary: Creates a data view. + summary: Create a data view operationId: createDataView description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -96,7 +99,7 @@ paths: $ref: '#/components/schemas/400_response' /s/{spaceId}/api/data_views/data_view/{viewId}: get: - summary: Retrieves a single data view by identifier. + summary: Get a data view operationId: getDataView description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -122,7 +125,7 @@ paths: schema: $ref: '#/components/schemas/404_response' delete: - summary: Deletes a data view. + summary: Delete a data view operationId: deleteDataView description: | WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -142,7 +145,7 @@ paths: schema: $ref: '#/components/schemas/404_response' post: - summary: Updates a data view. + summary: Update a data view operationId: updateDataView description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -176,7 +179,7 @@ paths: $ref: '#/components/schemas/400_response' /s/{spaceId}/api/data_views/default: get: - summary: Retrieves the default data view identifier. + summary: Get the default data view identifier operationId: getDefaultDataView description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -204,7 +207,7 @@ paths: schema: $ref: '#/components/schemas/400_response' post: - summary: Sets the default data view identifier. + summary: Sets the default data view identifier operationId: setDefaultDatailView description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -223,9 +226,8 @@ paths: - data_view_id properties: data_view_id: - type: - - string - - 'null' + type: string + nullable: true description: | The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view. force: @@ -253,10 +255,10 @@ paths: $ref: '#/components/schemas/400_response' /s/{spaceId}/api/data_views/data_view/{viewId}/fields: post: - summary: Update fields presentation metadata such as count, customLabel and format. + summary: Update data view fields metadata operationId: updateFieldsMetadata description: | - This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. + Update fields presentation metadata such as count, customLabel and format. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. tags: - data views parameters: @@ -296,7 +298,7 @@ paths: $ref: '#/components/schemas/400_response' /s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field: post: - summary: Creates a runtime field. + summary: Create a runtime field operationId: createRuntimeField description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -327,8 +329,15 @@ paths: examples: createRuntimeFieldRequest: $ref: '#/components/examples/create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object put: - summary: Create or update an existing runtime field. + summary: Create or update a runtime field operationId: createUpdateRuntimeField description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -379,9 +388,6 @@ paths: type: array items: type: object - examples: - createRuntimeFieldResponse: - $ref: '#/components/examples/create_runtime_field_response' '400': description: Bad request content: @@ -390,7 +396,7 @@ paths: $ref: '#/components/schemas/400_response' /s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field/{fieldName}: get: - summary: Retrieves a runtime field. + summary: Get a runtime field operationId: getRuntimeField description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -424,7 +430,7 @@ paths: schema: $ref: '#/components/schemas/404_response' delete: - summary: Delete a runtime field from a data view. + summary: Delete a runtime field from a data view operationId: deleteRuntimeField description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -444,7 +450,7 @@ paths: schema: $ref: '#/components/schemas/404_response' post: - summary: Update an existing runtime field. + summary: Update a runtime field operationId: updateRuntimeField description: | This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -484,6 +490,461 @@ paths: application/json: schema: $ref: '#/components/schemas/400_response' + /api/data_views: + get: + summary: Get all data views in the default space + operationId: getAllDataViewsDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + namespaces: + type: array + items: + type: string + title: + type: string + typeMeta: + type: object + examples: + getAllDataViewsResponse: + $ref: '#/components/examples/get_data_views_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + /api/data_views/data_view: + post: + summary: Create a data view in the default space + operationId: createDataViewDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/create_data_view_request_object' + examples: + createDataViewRequest: + $ref: '#/components/examples/create_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/data_view_response_object' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + /api/data_views/data_view/{viewId}: + get: + summary: Get a data view in the default space + operationId: getDataViewDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/view_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/data_view_response_object' + examples: + getDataViewResponse: + $ref: '#/components/examples/get_data_view_response' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/404_response' + delete: + summary: Delete a data view from the default space + operationId: deleteDataViewDefault + description: | + WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/view_id' + responses: + '204': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/404_response' + post: + summary: Update a data view in the default space + operationId: updateDataViewDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/view_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/update_data_view_request_object' + examples: + updateDataViewRequest: + $ref: '#/components/examples/update_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/data_view_response_object' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + /api/data_views/data_view/{viewId}/fields: + post: + summary: Update data view fields metadata in the default space + operationId: updateFieldsMetadataDefault + description: | + Update fields presentation metadata such as count, customLabel and format. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - fields + properties: + fields: + description: The field object. + type: object + examples: + updateFieldsMetadataRequest: + $ref: '#/components/examples/update_field_metadata_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + /api/data_views/data_view/{viewId}/runtime_field: + post: + summary: Create a runtime field in the default space + operationId: createRuntimeFieldDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + createRuntimeFieldRequest: + $ref: '#/components/examples/create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + put: + summary: Create or update a runtime field in the default space + operationId: createUpdateRuntimeFieldDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - name: viewId + in: path + description: | + The ID of the data view fields you want to update. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + updateRuntimeFieldRequest: + $ref: '#/components/examples/create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + /api/data_views/data_view/{viewId}/runtime_field/{fieldName}: + get: + summary: Get a runtime field in the default space + operationId: getRuntimeFieldDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/field_name' + - $ref: '#/components/parameters/view_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + examples: + getRuntimeFieldResponse: + $ref: '#/components/examples/get_runtime_field_response' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/404_response' + delete: + summary: Delete a runtime field from a data view in the default space + operationId: deleteRuntimeFieldDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/field_name' + - $ref: '#/components/parameters/view_id' + responses: + '200': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/404_response' + post: + summary: Update a runtime field in the default space + operationId: updateRuntimeFieldDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/field_name' + - $ref: '#/components/parameters/view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - runtimeField + properties: + runtimeField: + type: object + description: | + The runtime field definition object. + + You can update following fields: + + - `type` + - `script` + examples: + updateRuntimeFieldRequest: + $ref: '#/components/examples/update_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + /api/data_views/default: + get: + summary: Get the default data view in the default space + operationId: getDefaultDataViewDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view_id: + type: string + examples: + getDefaultDataViewResponse: + $ref: '#/components/examples/get_default_data_view_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + post: + summary: Set the default data view in the default space + operationId: setDefaultDatailViewDefault + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - data_view_id + properties: + data_view_id: + type: string + nullable: true + description: | + The data view identifier. NOTE: The API does not validate whether it is a valid identifier. Use `null` to unset the default data view. + force: + type: boolean + description: Update an existing default data view identifier. + default: false + examples: + setDefaultDataViewRequest: + $ref: '#/components/examples/set_default_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' components: securitySchemes: basicAuth: @@ -493,7 +954,8 @@ components: type: apiKey in: header name: Authorization - description: 'e.g. Authorization: ApiKey base64AccessApiKey' + description: | + Serverless APIs support only key-based authentication. You must create an API key and use the encoded value in the request header. For example: 'Authorization: ApiKey base64AccessApiKey'. parameters: space_id: in: path @@ -502,8 +964,7 @@ components: required: true schema: type: string - examples: - - default + example: default kbn_xsrf: schema: type: string @@ -1518,13 +1979,6 @@ components: type: long script: source: emit(doc["foo"].value) - create_runtime_field_response: - summary: The API returns created runtime field object array and updated data view object. - value: - data_view: - ...: null - fields: - - ... get_runtime_field_response: summary: The get runtime field API returns a JSON object that contains information about the runtime field (`hour_of_day`) and the data view (`d3d7af60-4c81-11e8-b3d7-01146121b73d`). value: diff --git a/src/plugins/data_views/docs/openapi/components/parameters/space_id.yaml b/src/plugins/data_views/docs/openapi/components/parameters/space_id.yaml index 45787e844caec..0a9fba457e3e7 100644 --- a/src/plugins/data_views/docs/openapi/components/parameters/space_id.yaml +++ b/src/plugins/data_views/docs/openapi/components/parameters/space_id.yaml @@ -4,5 +4,4 @@ description: An identifier for the space. If `/s/` and the identifier are omitte required: true schema: type: string - examples: - - default + example: default diff --git a/src/plugins/data_views/docs/openapi/entrypoint.yaml b/src/plugins/data_views/docs/openapi/entrypoint.yaml index 86d76dbfa42d4..fdd0d3054a4c8 100644 --- a/src/plugins/data_views/docs/openapi/entrypoint.yaml +++ b/src/plugins/data_views/docs/openapi/entrypoint.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Data views description: OpenAPI schema for data view endpoints @@ -12,38 +12,41 @@ tags: - name: data views description: Data view APIs enable you to manage data views, formerly known as Kibana index patterns. servers: - - url: / + - url: 'https://{kibana_url}' + variables: + kibana_url: + default: localhost:5601 paths: -# Default space - # '/api/data_views': - # $ref: 'paths/api@data_views.yaml' - # '/api/data_views/data_view': - # $ref: 'paths/api@data_views@data_view.yaml' - # '/api/data_views/data_view/{viewId}': - # $ref: 'paths/api@data_views@data_view@{viewid}.yaml' - # '/api/data_views/data_view/{viewId}/fields': - # $ref: 'paths/api@data_views@data_view@{viewid}@fields.yaml' - # '/api/data_views/data_view/{viewId}/runtime_field': - # $ref: 'paths/api@data_views@data_view@{viewid}@runtime_field.yaml' - # '/api/data_views/data_view/{viewId}/runtime_field/{fieldName}': - # $ref: 'paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml' - # '/api/data_views/default': - # $ref: 'paths/api@data_views@default.yaml' # Non-default space - '/s/{spaceId}/api/data_views': - $ref: 'paths/s@{spaceid}@api@data_views.yaml' - '/s/{spaceId}/api/data_views/data_view': - $ref: 'paths/s@{spaceid}@api@data_views@data_view.yaml' - '/s/{spaceId}/api/data_views/data_view/{viewId}': - $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}.yaml' - '/s/{spaceId}/api/data_views/default': - $ref: 'paths/s@{spaceid}@api@data_views@default.yaml' - '/s/{spaceId}/api/data_views/data_view/{viewId}/fields': - $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}@fields.yaml' - '/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field': - $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field.yaml' - '/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field/{fieldName}': - $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml' + '/s/{spaceId}/api/data_views': + $ref: 'paths/s@{spaceid}@api@data_views.yaml' + '/s/{spaceId}/api/data_views/data_view': + $ref: 'paths/s@{spaceid}@api@data_views@data_view.yaml' + '/s/{spaceId}/api/data_views/data_view/{viewId}': + $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}.yaml' + '/s/{spaceId}/api/data_views/default': + $ref: 'paths/s@{spaceid}@api@data_views@default.yaml' + '/s/{spaceId}/api/data_views/data_view/{viewId}/fields': + $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}@fields.yaml' + '/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field': + $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field.yaml' + '/s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field/{fieldName}': + $ref: 'paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml' +# Default space + '/api/data_views': + $ref: 'paths/api@data_views.yaml' + '/api/data_views/data_view': + $ref: 'paths/api@data_views@data_view.yaml' + '/api/data_views/data_view/{viewId}': + $ref: 'paths/api@data_views@data_view@{viewid}.yaml' + '/api/data_views/data_view/{viewId}/fields': + $ref: 'paths/api@data_views@data_view@{viewid}@fields.yaml' + '/api/data_views/data_view/{viewId}/runtime_field': + $ref: 'paths/api@data_views@data_view@{viewid}@runtime_field.yaml' + '/api/data_views/data_view/{viewId}/runtime_field/{fieldName}': + $ref: 'paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml' + '/api/data_views/default': + $ref: 'paths/api@data_views@default.yaml' components: securitySchemes: basicAuth: @@ -53,7 +56,10 @@ components: type: apiKey in: header name: Authorization - description: 'e.g. Authorization: ApiKey base64AccessApiKey' + description: > + Serverless APIs support only key-based authentication. + You must create an API key and use the encoded value in the request header. + For example: 'Authorization: ApiKey base64AccessApiKey'. security: - basicAuth: [] - apiKeyAuth: [] diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml new file mode 100644 index 0000000000000..d68e957bdef10 --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml @@ -0,0 +1,41 @@ +get: + summary: Get all data views in the default space + operationId: getAllDataViewsDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + namespaces: + type: array + items: + type: string + title: + type: string + typeMeta: + type: object + examples: + getAllDataViewsResponse: + $ref: '../components/examples/get_data_views_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml new file mode 100644 index 0000000000000..95946468456fc --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml @@ -0,0 +1,31 @@ +post: + summary: Create a data view in the default space + operationId: createDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/create_data_view_request_object.yaml' + examples: + createDataViewRequest: + $ref: '../components/examples/create_data_view_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/data_view_response_object.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml new file mode 100644 index 0000000000000..700bf7e5a8b65 --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml @@ -0,0 +1,79 @@ +get: + summary: Get a data view in the default space + operationId: getDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/parameters/view_id.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/data_view_response_object.yaml' + examples: + getDataViewResponse: + $ref: '../components/examples/get_data_view_response.yaml' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '../components/schemas/404_response.yaml' + +delete: + summary: Delete a data view from the default space + operationId: deleteDataViewDefault + description: > + WARNING: When you delete a data view, it cannot be recovered. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/view_id.yaml' + responses: + '204': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '../components/schemas/404_response.yaml' + +post: + summary: Update a data view in the default space + operationId: updateDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/view_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/update_data_view_request_object.yaml' + examples: + updateDataViewRequest: + $ref: '../components/examples/update_data_view_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/data_view_response_object.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml new file mode 100644 index 0000000000000..58dd10b88b5d3 --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml @@ -0,0 +1,42 @@ +post: + summary: Update data view fields metadata in the default space + operationId: updateFieldsMetadataDefault + description: > + Update fields presentation metadata such as count, customLabel and format. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/view_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - fields + properties: + fields: + description: The field object. + type: object + examples: + updateFieldsMetadataRequest: + $ref: '../components/examples/update_field_metadata_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml new file mode 100644 index 0000000000000..db0fcd61c7959 --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml @@ -0,0 +1,99 @@ +post: + summary: Create a runtime field in the default space + operationId: createRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/view_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + createRuntimeFieldRequest: + $ref: '../components/examples/create_runtime_field_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + +put: + summary: Create or update a runtime field in the default space + operationId: createUpdateRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - name: viewId + in: path + description: | + The ID of the data view fields you want to update. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + updateRuntimeFieldRequest: + $ref: '../components/examples/create_runtime_field_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + # examples: + # createRuntimeFieldResponse: + # $ref: '../components/examples/create_runtime_field_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml new file mode 100644 index 0000000000000..e94dcd1b5feea --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml @@ -0,0 +1,94 @@ +get: + summary: Get a runtime field in the default space + operationId: getRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/parameters/field_name.yaml' + - $ref: '../components/parameters/view_id.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + examples: + getRuntimeFieldResponse: + $ref: '../components/examples/get_runtime_field_response.yaml' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '../components/schemas/404_response.yaml' + +delete: + summary: Delete a runtime field from a data view in the default space + operationId: deleteRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/parameters/field_name.yaml' + - $ref: '../components/parameters/view_id.yaml' + responses: + '200': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '../components/schemas/404_response.yaml' + +post: + summary: Update a runtime field in the default space + operationId: updateRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/parameters/field_name.yaml' + - $ref: '../components/parameters/view_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - runtimeField + properties: + runtimeField: + type: object + description: | + The runtime field definition object. + + You can update following fields: + + - `type` + - `script` + examples: + updateRuntimeFieldRequest: + $ref: '../components/examples/update_runtime_field_request.yaml' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml new file mode 100644 index 0000000000000..89628f7e25820 --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml @@ -0,0 +1,74 @@ +get: + summary: Get the default data view in the default space + operationId: getDefaultDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view_id: + type: string + examples: + getDefaultDataViewResponse: + $ref: '../components/examples/get_default_data_view_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' +post: + summary: Set the default data view in the default space + operationId: setDefaultDatailViewDefault + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - data_view_id + properties: + data_view_id: + type: string + nullable: true + description: > + The data view identifier. + NOTE: The API does not validate whether it is a valid identifier. + Use `null` to unset the default data view. + force: + type: boolean + description: Update an existing default data view identifier. + default: false + examples: + setDefaultDataViewRequest: + $ref: '../components/examples/set_default_data_view_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views.yaml index b51fd231e4332..25430e76ab629 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a list of all data views. + summary: Get all data views operationId: getAllDataViews description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view.yaml index 230427f30187d..d9ae9f1ff5b30 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view.yaml @@ -1,5 +1,5 @@ post: - summary: Creates a data view. + summary: Create a data view operationId: createDataView description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}.yaml index 157899bcb578f..eedecfc8c7a70 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a single data view by identifier. + summary: Get a data view operationId: getDataView description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -26,7 +26,7 @@ get: $ref: '../components/schemas/404_response.yaml' delete: - summary: Deletes a data view. + summary: Delete a data view operationId: deleteDataView description: > WARNING: When you delete a data view, it cannot be recovered. @@ -48,7 +48,7 @@ delete: $ref: '../components/schemas/404_response.yaml' post: - summary: Updates a data view. + summary: Update a data view operationId: updateDataView description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@fields.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@fields.yaml index 5e7911e6b7aec..be7cda589cdf1 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@fields.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@fields.yaml @@ -1,7 +1,8 @@ post: - summary: Update fields presentation metadata such as count, customLabel and format. + summary: Update data view fields metadata operationId: updateFieldsMetadata description: > + Update fields presentation metadata such as count, customLabel and format. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. tags: - data views diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field.yaml index dcc2783a82afa..baaf197446838 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field.yaml @@ -1,5 +1,5 @@ post: - summary: Creates a runtime field. + summary: Create a runtime field operationId: createRuntimeField description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -30,9 +30,16 @@ post: examples: createRuntimeFieldRequest: $ref: '../components/examples/create_runtime_field_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object put: - summary: Create or update an existing runtime field. + summary: Create or update a runtime field operationId: createUpdateRuntimeField description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -83,9 +90,9 @@ put: type: array items: type: object - examples: - createRuntimeFieldResponse: - $ref: '../components/examples/create_runtime_field_response.yaml' + # examples: + # createRuntimeFieldResponse: + # $ref: '../components/examples/create_runtime_field_response.yaml' '400': description: Bad request content: diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml index 7508613089a47..6f9f4fc1b3fa4 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a runtime field. + summary: Get a runtime field operationId: getRuntimeField description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -34,7 +34,7 @@ get: $ref: '../components/schemas/404_response.yaml' delete: - summary: Delete a runtime field from a data view. + summary: Delete a runtime field from a data view operationId: deleteRuntimeField description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -55,7 +55,7 @@ delete: $ref: '../components/schemas/404_response.yaml' post: - summary: Update an existing runtime field. + summary: Update a runtime field operationId: updateRuntimeField description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. diff --git a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@default.yaml b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@default.yaml index 6664e1fc45f97..aec99b494fd63 100644 --- a/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@default.yaml +++ b/src/plugins/data_views/docs/openapi/paths/s@{spaceid}@api@data_views@default.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves the default data view identifier. + summary: Get the default data view identifier operationId: getDefaultDataView description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -27,7 +27,7 @@ get: schema: $ref: '../components/schemas/400_response.yaml' post: - summary: Sets the default data view identifier. + summary: Sets the default data view identifier operationId: setDefaultDatailView description: > This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. @@ -46,7 +46,8 @@ post: - data_view_id properties: data_view_id: - type: ['string', 'null'] + type: string + nullable: true description: > The data view identifier. NOTE: The API does not validate whether it is a valid identifier. From e9f94100232f1e092d8efcf38e2b8d47e7d474fa Mon Sep 17 00:00:00 2001 From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:49:24 +0100 Subject: [PATCH 019/127] [Mappings Editor] Add support for subobjects parameter (#184763) Fixes https://github.com/elastic/kibana/issues/183714 ## Summary This PR adds support for the `subobjects` mappings parameter and mappings configuration under "Advanced options" in the Mappings editor UI. Screenshot 2024-06-06 at 15 54 11 Screenshot 2024-06-06 at 15 58 32 **How to test:** 1. Start Es and Kibana 2. Go to Index Management -> Index Templates/Component Templates and start creating a index/component template. 3. Go to the Mappings step and create a field of type `object`. Edit this field and toggle the `subobjects` field. 4. Go to the "Advanced options" tab and toggle the `subobjects` field. 5. Go to the last Review step and verify that the preview of the template contains the correct `subobjects` value. 6. Save the template and then start editing it. Verify that the `subobject` field is correctly populated in the form. Test loading a JSON: 1. Start Es and Kibana 2. Go to Index Management -> Index Templates/Component Templates and start creating a index/component template. 7. At the Mappings step, click on the "Load JSON" button. 8. Add the following mappings object (taken from the first example in [Es docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/subobjects.html#subobjects)): ``` { "properties": { "metrics": { "type": "object", "subobjects": false } } } ``` 9. Save and go to the Mappings editor - verify that the mappings field is correctly displayed in the editor with the correct `subobjects` field. 10. If creating an index template, click the "Preview index template" button and verify that the `subobjects` parameter is displayed. 11. Finish creating the template and verify it has the `subobjects` parameter in the `mappings` property. 12. Test also loading a JSON with a `subobject` mapping configuration: ``` { "subobjects": false } ``` Then verify this mappings configuration is correctly applied to the index/component template. --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + .../mappings_editor.test.tsx | 1 + .../configuration_form/configuration_form.tsx | 7 +++ .../configuration_form_schema.tsx | 6 ++ .../configuration_form/subobjects_section.tsx | 60 +++++++++++++++++++ .../document_fields/field_parameters/index.ts | 2 + .../field_parameters/subobjects_parameter.tsx | 36 +++++++++++ .../fields/field_types/object_type.tsx | 4 +- .../constants/parameters_definition.tsx | 6 ++ .../lib/extract_mappings_definition.test.ts | 1 + .../lib/mappings_validator.test.ts | 6 ++ .../mappings_editor/lib/mappings_validator.ts | 1 + .../mappings_editor/types/document_fields.ts | 3 +- .../components/mappings_editor/types/state.ts | 1 + .../application/services/documentation.ts | 6 ++ .../application/shared/parse_mappings.ts | 2 + 16 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/subobjects_section.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/subobjects_parameter.tsx diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index c79988f4ea964..0a6f4a06c38ef 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -421,6 +421,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D mappingSourceFields: `${ELASTICSEARCH_DOCS}mapping-source-field.html`, mappingSourceFieldsDisable: `${ELASTICSEARCH_DOCS}mapping-source-field.html#disable-source-field`, mappingStore: `${ELASTICSEARCH_DOCS}mapping-store.html`, + mappingSubobjects: `${ELASTICSEARCH_DOCS}subobjects.html`, mappingTermVector: `${ELASTICSEARCH_DOCS}term-vector.html`, mappingTypesRemoval: `${ELASTICSEARCH_DOCS}removal-of-types.html`, migrateIndexAllocationFilters: `${ELASTICSEARCH_DOCS}migrate-index-allocation-filters.html`, diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx index 33f97c6f61c8f..1347aaeade4f8 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx @@ -324,6 +324,7 @@ describe('Mappings editor: core', () => { _routing: { required: false, }, + subobjects: true, }; await act(async () => { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx index 571449a5de29e..b326779d8a76c 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx @@ -19,6 +19,7 @@ import { SourceFieldSection } from './source_field_section'; import { MetaFieldSection } from './meta_field_section'; import { RoutingSection } from './routing_section'; import { MapperSizePluginSection } from './mapper_size_plugin_section'; +import { SubobjectsSection } from './subobjects_section'; import { configurationFormSchema } from './configuration_form_schema'; interface Props { @@ -42,6 +43,7 @@ const formSerializer = (formData: GenericObject, sourceFieldMode?: string) => { metaField, _routing, _size, + subobjects, } = formData; const dynamic = dynamicMappingsEnabled ? true : throwErrorsForUnmappedFields ? 'strict' : false; @@ -55,6 +57,7 @@ const formSerializer = (formData: GenericObject, sourceFieldMode?: string) => { _meta: metaField, _routing, _size, + subobjects, }; return serialized; @@ -77,6 +80,7 @@ const formDeserializer = (formData: GenericObject) => { _routing, // For the Mapper Size plugin _size, + subobjects, } = formData; return { @@ -95,6 +99,7 @@ const formDeserializer = (formData: GenericObject) => { metaField: _meta ?? {}, _routing, _size, + subobjects, }; }; @@ -177,6 +182,8 @@ export const ConfigurationForm = React.memo(({ value, esNodesPlugins }: Props) = )} {isMapperSizeSectionVisible && } + + ); }); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx index 843c5aed6ece5..a9913b9474b36 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx @@ -186,4 +186,10 @@ export const configurationFormSchema: FormSchema = { defaultValue: false, }, }, + subobjects: { + label: i18n.translate('xpack.idxMgmt.mappingsEditor.configuration.subobjectsLabel', { + defaultMessage: 'Allow objects to hold further subobjects', + }), + defaultValue: true, + }, }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/subobjects_section.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/subobjects_section.tsx new file mode 100644 index 0000000000000..f858474a45086 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/subobjects_section.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiLink, EuiCode } from '@elastic/eui'; + +import { documentationService } from '../../../../services/documentation'; +import { UseField, FormRow, ToggleField } from '../../shared_imports'; + +export const SubobjectsSection = () => { + return ( + + {i18n.translate('xpack.idxMgmt.mappingsEditor.subobjectsParameterName', { + defaultMessage: 'subobjects', + })} + + ), + false: ( + + {i18n.translate('xpack.idxMgmt.mappingsEditor.subobjectsParameterFalseValue', { + defaultMessage: 'false', + })} + + ), + docsLink: ( + + {i18n.translate('xpack.idxMgmt.mappingsEditor.subobjectsDocumentionLink', { + defaultMessage: 'Learn more.', + })} + + ), + }} + /> + } + > + + + ); +}; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts index b946f4c262bdd..d22b128205399 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts @@ -74,6 +74,8 @@ export * from './meta_parameter'; export * from './ignore_above_parameter'; +export * from './subobjects_parameter'; + export const PARAMETER_SERIALIZERS = [relationsSerializer, dynamicSerializer]; export const PARAMETER_DESERIALIZERS = [relationsDeserializer, dynamicDeserializer]; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/subobjects_parameter.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/subobjects_parameter.tsx new file mode 100644 index 0000000000000..c5eea5fa111a3 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/subobjects_parameter.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +import { documentationService } from '../../../../../services/documentation'; +import { EditFieldFormRow } from '../fields/edit_field'; + +export const SubobjectsParameter = () => { + return ( + + ); +}; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx index 2417561a15519..d8d5953d33421 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { NormalizedField } from '../../../../types'; -import { DynamicParameter, EnabledParameter } from '../../field_parameters'; +import { DynamicParameter, EnabledParameter, SubobjectsParameter } from '../../field_parameters'; import { BasicParametersSection } from '../edit_field'; interface Props { @@ -23,6 +23,8 @@ export const ObjectType = ({ field }: Props) => { /> + + ); }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx index 881318b52cdc5..790b4560000f7 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx @@ -1119,4 +1119,10 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio }, schema: t.boolean, }, + subobjects: { + fieldConfig: { + defaultValue: true, + }, + schema: t.boolean, + }, }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts index 33205bbf9d716..3e67f35a5fccc 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts @@ -126,6 +126,7 @@ describe('extractMappingsDefinition', () => { _size: { enabled: true, }, + subobjects: true, }; expect(extractMappingsDefinition(mappings)).toBe(mappings); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts index 94af72c5e2902..288b2f3ca37fd 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts @@ -40,6 +40,7 @@ describe('Mappings configuration validator', () => { _size: { enabled: true, }, + subobjects: true, }; const { errors } = validateMappings(mappings, [MapperSizePluginId]); @@ -59,6 +60,7 @@ describe('Mappings configuration validator', () => { }, properties: { title: { type: 'text' } }, dynamic_templates: [], + subobjects: true, unknown: 123, }; @@ -85,6 +87,7 @@ describe('Mappings configuration validator', () => { _size: { enabled: true, }, + subobjects: true, }; const { value, errors } = validateMappings(mappings, []); @@ -93,6 +96,7 @@ describe('Mappings configuration validator', () => { dynamic: true, properties: {}, dynamic_templates: [], + subobjects: true, }); expect(errors).not.toBe(undefined); @@ -309,6 +313,7 @@ describe('Properties validator', () => { depth_limit: true, dims: false, max_shingle_size: 'string_not_allowed', + subobjects: 'abc', }, // All the parameters in "goodField" have the correct format // and should still be there after the validation ran. @@ -361,6 +366,7 @@ describe('Properties validator', () => { depth_limit: 20, dims: 'abc', max_shingle_size: 2, + subobjects: true, }, goodField2: { type: 'object', diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts index 08494cdd3ca64..c4e0f122e1492 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts @@ -238,6 +238,7 @@ export const mappingsConfigurationSchema = t.exact( _size: t.interface({ enabled: t.boolean, }), + subobjects: t.boolean, }) ); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts index b8a024b0e98e5..53f553f8659ad 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts @@ -164,7 +164,8 @@ export type ParameterName = | 'value' | 'meta' | 'time_series_metric' - | 'time_series_dimension'; + | 'time_series_dimension' + | 'subobjects'; export interface Parameter { fieldConfig: FieldConfig; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/state.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/state.ts index d08c80835c620..a0e7247c39bc1 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/state.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/state.ts @@ -36,6 +36,7 @@ export interface MappingsConfiguration { }; _meta?: string; _size?: { enabled: boolean }; + subobjects?: boolean; } export interface MappingsTemplates { diff --git a/x-pack/plugins/index_management/public/application/services/documentation.ts b/x-pack/plugins/index_management/public/application/services/documentation.ts index 71d16b84e6639..58aba69351883 100644 --- a/x-pack/plugins/index_management/public/application/services/documentation.ts +++ b/x-pack/plugins/index_management/public/application/services/documentation.ts @@ -56,6 +56,7 @@ class DocumentationService { private mappingSourceFields: string = ''; private mappingSourceFieldsDisable: string = ''; private mappingStore: string = ''; + private mappingSubobjects: string = ''; private mappingTermVector: string = ''; private mappingTypesRemoval: string = ''; private percolate: string = ''; @@ -115,6 +116,7 @@ class DocumentationService { this.mappingSourceFields = links.elasticsearch.mappingSourceFields; this.mappingSourceFieldsDisable = links.elasticsearch.mappingSourceFieldsDisable; this.mappingStore = links.elasticsearch.mappingStore; + this.mappingSubobjects = links.elasticsearch.mappingSubobjects; this.mappingTermVector = links.elasticsearch.mappingTermVector; this.mappingTypesRemoval = links.elasticsearch.mappingTypesRemoval; this.percolate = links.query.percolate; @@ -329,6 +331,10 @@ class DocumentationService { return this.mappingEnabled; } + public getSubobjectsLink() { + return this.mappingSubobjects; + } + public getRuntimeFields() { return this.runtimeFields; } diff --git a/x-pack/plugins/index_management/public/application/shared/parse_mappings.ts b/x-pack/plugins/index_management/public/application/shared/parse_mappings.ts index 239b58169a713..3090d910034b2 100644 --- a/x-pack/plugins/index_management/public/application/shared/parse_mappings.ts +++ b/x-pack/plugins/index_management/public/application/shared/parse_mappings.ts @@ -35,6 +35,7 @@ export const parseMappings = ( dynamic_date_formats, dynamic_templates, /* eslint-enable @typescript-eslint/naming-convention */ + subobjects, } = mappingsDefinition; const parsed = { @@ -47,6 +48,7 @@ export const parseMappings = ( numeric_detection, date_detection, dynamic_date_formats, + subobjects, }, fields: properties, templates: { From c7b5af6fa094c7201c0bdaa09d01099fe0d23b44 Mon Sep 17 00:00:00 2001 From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:52:28 +0100 Subject: [PATCH 020/127] [Watcher] Fix page crash when showing request of a watch with metadata (#185026) Fixes https://github.com/elastic/kibana/issues/170665 ## Summary This PR fixes the blank page when "Show request" is clicked for a watch that has a `metadata` property set. The reason for the page crash is that previously we used the `set` lodash function to update the `metadata` object which directly modifies the `metadata` object, which is part of the `payload` prop of the [RequestFlyout](https://github.com/elastic/kibana/blob/1b8236375a1d969e651eb172916e8fbb19dbeb6b/x-pack/plugins/watcher/public/application/sections/watch_edit_page/components/request_flyout.tsx#L29) component. Since the prop is changed, the RequestFlyout component is re-rendered and the `serializeJsonWatch` function is called again, and so an infinite loop is created. With the new approach, we make sure that the original `metadata` object is not modified so that we avoid infinite rerendering. https://github.com/elastic/kibana/assets/59341489/ff76fdc7-8694-4414-a253-206e32954fee **How to test:** 1. Create the following watch: ``` PUT _watcher/watch/watchywatch { "trigger": { "schedule": { "interval": "30m" } }, "input": { "search": { "request": { "search_type": "query_then_fetch", "indices": [ "metricbeat-*" ], "rest_total_hits_as_int": true, "body": { "size": 0, "query": { "match_all": {} } } } } }, "condition": { "compare": { "ctx.payload.hits.total": { "gte": 10 } } }, "actions": { "my-logging-action": { "logging": { "level": "info", "text": "There are {{ctx.payload.hits.total}} documents in your index. Threshold is 10." } } }, "metadata": { "watcher_id": "watcher_test_sg", "description": "Watcher Test Description" } } ``` 2. Navigate to Watcher UI --> edit watch --> Click "Show request" 3. Verify that the request is displayed and the page doesn't crash. Note about testing: I haven't added additional tests as there are already [unit tests](https://github.com/elastic/kibana/blob/1b8236375a1d969e651eb172916e8fbb19dbeb6b/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.test.js#L34) for the `serializeJsonWatch` function that cover the case when there is a `metadata` property. --- .../common/lib/serialization/serialize_json_watch.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.js b/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.js index d614ea325da57..0b7e2506477d8 100644 --- a/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.js +++ b/x-pack/plugins/watcher/common/lib/serialization/serialize_json_watch.js @@ -5,17 +5,21 @@ * 2.0. */ -import { set } from '@kbn/safer-lodash-set'; import { WATCH_TYPES } from '../../constants'; export function serializeJsonWatch(name, json) { // We don't want to overwrite any metadata provided by the consumer. const { metadata = {} } = json; - set(metadata, 'xpack.type', WATCH_TYPES.JSON); const serializedWatch = { ...json, - metadata, + metadata: { + ...metadata, + xpack: { + ...metadata.xpack, + type: WATCH_TYPES.JSON, + }, + }, }; if (name) { From 1cca8095d02f5421923be8b119d22e4fdd84b442 Mon Sep 17 00:00:00 2001 From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com> Date: Mon, 17 Jun 2024 18:08:19 +0100 Subject: [PATCH 021/127] [Rollups] Add deprecated prompt (#185896) Closes https://github.com/elastic/kibana/issues/185861 ## Summary This PR replaces the empty prompt in Rollup Jobs with a deprecation prompt: Screenshot 2024-06-10 at 17 55 38

**How to test:** 1. Start Es and Kibana 2. Go to Stack Management -> Rollup Jobs 3. Since there are no existing rollup jobs, verify that the deprecation prompt is displayed and the Downsampling documentation link is correct. ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + packages/kbn-doc-links/src/types.ts | 1 + .../sections/job_list/deprecated_prompt.tsx | 54 +++++++++++++++++++ .../crud_app/sections/job_list/job_list.js | 50 ++--------------- .../sections/job_list/job_list.test.js | 4 +- .../translations/translations/fr-FR.json | 3 -- .../translations/translations/ja-JP.json | 3 -- .../translations/translations/zh-CN.json | 3 -- .../functional/apps/rollup_job/rollup_jobs.js | 5 ++ .../functional/page_objects/rollup_page.ts | 3 +- 10 files changed, 68 insertions(+), 59 deletions(-) create mode 100644 x-pack/plugins/rollup/public/crud_app/sections/job_list/deprecated_prompt.tsx diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 0a6f4a06c38ef..00899f64f3d63 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -842,6 +842,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D datastreamsManualRollover: `${ELASTICSEARCH_DOCS}use-a-data-stream.html#manually-roll-over-a-data-stream`, datastreamsTSDS: `${ELASTICSEARCH_DOCS}tsds.html`, datastreamsTSDSMetrics: `${ELASTICSEARCH_DOCS}tsds.html#time-series-metric`, + datastreamsDownsampling: `${ELASTICSEARCH_DOCS}downsampling.html`, installElasticAgent: `${FLEET_DOCS}install-fleet-managed-elastic-agent.html`, installElasticAgentStandalone: `${FLEET_DOCS}install-standalone-elastic-agent.html`, upgradeElasticAgent: `${FLEET_DOCS}upgrade-elastic-agent.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 0f6070c4016e3..f7cd6ba482aac 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -534,6 +534,7 @@ export interface DocLinks { datastreamsManualRollover: string; datastreamsTSDS: string; datastreamsTSDSMetrics: string; + datastreamsDownsampling: string; installElasticAgent: string; installElasticAgentStandalone: string; packageSignatures: string; diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/deprecated_prompt.tsx b/x-pack/plugins/rollup/public/crud_app/sections/job_list/deprecated_prompt.tsx new file mode 100644 index 0000000000000..ecdae95e90813 --- /dev/null +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/deprecated_prompt.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Fragment } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiButton, EuiEmptyPrompt, EuiPageSection } from '@elastic/eui'; +import { documentationLinks } from '../../services/documentation_links'; + +export const DeprecatedPrompt = () => { + return ( + + + + + } + body={ + +

+ +

+
+ } + actions={ + + + + } + /> +
+ ); +}; diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js index 83641d6483817..04e88cd5848d2 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js @@ -11,7 +11,6 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { - EuiButton, EuiButtonEmpty, EuiEmptyPrompt, EuiPageHeader, @@ -22,11 +21,12 @@ import { import { withKibana } from '@kbn/kibana-react-plugin/public'; import { extractQueryParams, SectionLoading } from '../../../shared_imports'; -import { getRouterLinkProps, listBreadcrumb } from '../../services'; +import { listBreadcrumb } from '../../services'; import { documentationLinks } from '../../services/documentation_links'; import { JobTable } from './job_table'; import { DetailPanel } from './detail_panel'; +import { DeprecatedPrompt } from './deprecated_prompt'; const REFRESH_RATE_MS = 30000; @@ -132,50 +132,6 @@ export class JobListUi extends Component { ); } - renderEmpty() { - return ( - - - - - } - body={ - -

- -

-
- } - actions={ - - - - } - /> -
- ); - } - renderLoading() { return ( @@ -235,7 +191,7 @@ export class JobListUi extends Component { content = this.renderError(jobLoadError); } } else if (!isLoading && !hasJobs) { - content = this.renderEmpty(); + content = ; } else if (isLoading) { content = this.renderLoading(); } else { diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js index d15376323c0d3..06c32a647e68d 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js @@ -52,10 +52,10 @@ const Component = (props) => ( const initTestBed = registerTestBed(Component, { defaultProps, store: rollupJobsStore }); describe('', () => { - it('should render empty prompt when loading is complete and there are no jobs', () => { + it('should render deprecated prompt when loading is complete and there are no rollup jobs', () => { const { exists } = initTestBed(); - expect(exists('jobListEmptyPrompt')).toBeTruthy(); + expect(exists('jobListDeprecatedPrompt')).toBeTruthy(); }); it('should display a loading message when loading the jobs', () => { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index b0abe61986bc1..eec216c68d584 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -31549,9 +31549,6 @@ "xpack.rollupJobs.jobDetails.tabSummary.sectionLogisticsLabel": "Logistique", "xpack.rollupJobs.jobDetails.tabSummary.sectionStatsTitle": "Statistiques", "xpack.rollupJobs.jobList.createButtonLabel": "Créer une tâche de cumul", - "xpack.rollupJobs.jobList.emptyPrompt.createButtonLabel": "Créer une tâche de cumul", - "xpack.rollupJobs.jobList.emptyPromptDescription": "Les tâches de cumul résument et stockent les données historiques dans un index plus petit pour une analyse ultérieure.", - "xpack.rollupJobs.jobList.emptyPromptTitle": "Créer votre première tâche de cumul", "xpack.rollupJobs.jobList.loadingErrorTitle": "Erreur lors du chargement des tâches de cumul", "xpack.rollupJobs.jobList.loadingTitle": "Chargement des tâches de cumul…", "xpack.rollupJobs.jobList.noPermissionText": "Vous n'êtes pas autorisé à afficher ou à ajouter des tâches de cumul.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9357810f33c97..e59e2a0379043 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -31525,9 +31525,6 @@ "xpack.rollupJobs.jobDetails.tabSummary.sectionLogisticsLabel": "ロジスティクス", "xpack.rollupJobs.jobDetails.tabSummary.sectionStatsTitle": "統計", "xpack.rollupJobs.jobList.createButtonLabel": "ロールアップジョブを作成", - "xpack.rollupJobs.jobList.emptyPrompt.createButtonLabel": "ロールアップジョブを作成", - "xpack.rollupJobs.jobList.emptyPromptDescription": "ロールアップジョブは、今後の分析用に履歴データを小さなインデックスに要約して格納します。", - "xpack.rollupJobs.jobList.emptyPromptTitle": "初めてのロールアップジョブの作成", "xpack.rollupJobs.jobList.loadingErrorTitle": "ロールアップジョブを読み込み中にエラーが発生", "xpack.rollupJobs.jobList.loadingTitle": "ロールアップジョブを読み込み中...", "xpack.rollupJobs.jobList.noPermissionText": "ロールアップジョブの表示または追加パーミッションがありません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 491f4d39d9f12..80a079b82c701 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -31566,9 +31566,6 @@ "xpack.rollupJobs.jobDetails.tabSummary.sectionLogisticsLabel": "运筹", "xpack.rollupJobs.jobDetails.tabSummary.sectionStatsTitle": "统计信息", "xpack.rollupJobs.jobList.createButtonLabel": "创建汇总/打包作业", - "xpack.rollupJobs.jobList.emptyPrompt.createButtonLabel": "创建汇总/打包作业", - "xpack.rollupJobs.jobList.emptyPromptDescription": "汇总/打包作业可汇总历史数据并将其存储在较小的索引中以供将来分析。", - "xpack.rollupJobs.jobList.emptyPromptTitle": "创建您的首个汇总/打包作业", "xpack.rollupJobs.jobList.loadingErrorTitle": "加载汇总/打包作业时出错", "xpack.rollupJobs.jobList.loadingTitle": "正在加载汇总/打包作业……", "xpack.rollupJobs.jobList.noPermissionText": "您没有权限查看或添加汇总/打包作业。", diff --git a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js index 32b572202b5c2..bbf9d56e494ee 100644 --- a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js +++ b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js @@ -17,6 +17,7 @@ export default function ({ getService, getPageObjects }) { const esDeleteAllIndices = getService('esDeleteAllIndices'); const kibanaServer = getService('kibanaServer'); const es = getService('es'); + const testSubjects = getService('testSubjects'); const isRunningCcs = config.get('esTestCluster.ccs') ? true : false; let remoteEs; if (isRunningCcs) { @@ -53,6 +54,10 @@ export default function ({ getService, getPageObjects }) { await createMockRollupIndex(es); }); + it('shows deprecation prompt when there are no existing rollup jobs', async () => { + expect(await testSubjects.exists('jobListDeprecatedPrompt')).to.be(true); + }); + it('create new rollup job', async () => { const interval = '1000ms'; const esNode = isRunningCcs ? remoteEs : es; diff --git a/x-pack/test/functional/page_objects/rollup_page.ts b/x-pack/test/functional/page_objects/rollup_page.ts index f485de8ebac0c..90ba69f5410fb 100644 --- a/x-pack/test/functional/page_objects/rollup_page.ts +++ b/x-pack/test/functional/page_objects/rollup_page.ts @@ -13,6 +13,7 @@ export class RollupPageObject extends FtrService { private readonly log = this.ctx.getService('log'); private readonly find = this.ctx.getService('find'); private readonly header = this.ctx.getPageObject('header'); + private readonly common = this.ctx.getPageObject('common'); private readonly retry = this.ctx.getService('retry'); async createNewRollUpJob( @@ -26,7 +27,7 @@ export class RollupPageObject extends FtrService { ) { let stepNum = 1; // Step 1 - await this.testSubjects.click('createRollupJobButton'); + await this.common.navigateToUrlWithBrowserHistory('rollupJob', '/create'); await this.verifyStepIsActive(stepNum); await this.addRollupNameandIndexPattern(jobName, indexPattern); await this.verifyIndexPatternAccepted(); From 54839f14166c9ecefa37c7417da8505836041ac1 Mon Sep 17 00:00:00 2001 From: Achyut Jhunjhunwala Date: Mon, 17 Jun 2024 19:11:51 +0200 Subject: [PATCH 022/127] =?UTF-8?q?Add=20support=20to=20run=20synthtrace?= =?UTF-8?q?=20for=20locally=20running=20kibana=20serverless=20a=E2=80=A6?= =?UTF-8?q?=20(#186308)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds support for running synthtrace on locally running serverless kibana and es --- packages/kbn-apm-synthtrace/src/cli/utils/get_service_urls.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-apm-synthtrace/src/cli/utils/get_service_urls.ts b/packages/kbn-apm-synthtrace/src/cli/utils/get_service_urls.ts index 3f13cae5e039c..3967040a569af 100644 --- a/packages/kbn-apm-synthtrace/src/cli/utils/get_service_urls.ts +++ b/packages/kbn-apm-synthtrace/src/cli/utils/get_service_urls.ts @@ -12,7 +12,7 @@ import { Logger } from '../../lib/utils/create_logger'; import { RunOptions } from './parse_run_cli_flags'; async function discoverAuth(parsedTarget: Url) { - const possibleCredentials = [`admin:changeme`, `elastic:changeme`]; + const possibleCredentials = [`admin:changeme`, `elastic:changeme`, `elastic_serverless:changeme`]; for (const auth of possibleCredentials) { const url = format({ ...parsedTarget, From a9f5375fa89a275df6eeb625a25e7ba30bd7bbe4 Mon Sep 17 00:00:00 2001 From: rohanxz <115164234+rohanxz@users.noreply.github.com> Date: Mon, 17 Jun 2024 23:05:48 +0530 Subject: [PATCH 023/127] Gemini Connector Assistant Integration (#184741) --- .../impl/assistant/api/index.test.tsx | 12 +- .../impl/assistant/api/index.tsx | 8 +- .../use_load_connectors/index.tsx | 5 +- x-pack/packages/kbn-langchain/server/index.ts | 2 + .../server/language_models/constants.ts | 5 + .../language_models/simple_chat_model.test.ts | 9 +- .../language_models/simple_chat_model.ts | 13 +- .../kbn-langchain/server/utils/bedrock.ts | 9 +- .../kbn-langchain/server/utils/gemini.test.ts | 89 +++++ .../kbn-langchain/server/utils/gemini.ts | 80 +++++ .../kbn-langchain/server/utils/types.ts | 38 ++ .../connector_types.test.ts.snap | 338 +++++++++++++++++- .../server/lib/gen_ai_token_tracking.test.ts | 34 +- .../server/lib/gen_ai_token_tracking.ts | 37 +- ...get_token_count_from_invoke_stream.test.ts | 44 ++- .../lib/get_token_count_from_invoke_stream.ts | 64 ++++ .../server/lib/parse_stream.test.ts | 40 +++ .../server/lib/parse_stream.ts | 31 +- .../elastic_assistant/server/routes/utils.ts | 1 + .../stream/stream_observable.test.ts | 141 ++++++++ .../get_comments/stream/stream_observable.ts | 95 ++++- .../common/gemini/constants.ts | 2 + .../stack_connectors/common/gemini/schema.ts | 24 ++ .../stack_connectors/common/gemini/types.ts | 6 + .../public/connector_types/gemini/logo.tsx | 22 +- .../connector_types/gemini/gemini.test.ts | 299 +++++++++++++--- .../server/connector_types/gemini/gemini.ts | 160 ++++++++- 27 files changed, 1500 insertions(+), 108 deletions(-) create mode 100644 x-pack/packages/kbn-langchain/server/utils/gemini.test.ts create mode 100644 x-pack/packages/kbn-langchain/server/utils/gemini.ts create mode 100644 x-pack/packages/kbn-langchain/server/utils/types.ts diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx index c1c6f8e6a67aa..0182c4061866b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx @@ -134,7 +134,7 @@ describe('API tests', () => { ); }); - it('calls the non-stream API when assistantStreamingEnabled is true and actionTypeId is gemini and isEnabledKnowledgeBase is true', async () => { + it('calls the stream API when assistantStreamingEnabled is true and actionTypeId is gemini and isEnabledKnowledgeBase is true', async () => { const testProps: FetchConnectorExecuteAction = { ...fetchConnectorArgs, apiConfig: apiConfig.gemini, @@ -145,13 +145,13 @@ describe('API tests', () => { expect(mockHttp.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/actions/connector/foo/_execute', { - ...staticDefaults, - body: '{"message":"This is a test","subAction":"invokeAI","conversationId":"test","actionTypeId":".gemini","replacements":{},"isEnabledKnowledgeBase":true,"isEnabledRAGAlerts":false}', + ...streamingDefaults, + body: '{"message":"This is a test","subAction":"invokeStream","conversationId":"test","actionTypeId":".gemini","replacements":{},"isEnabledKnowledgeBase":true,"isEnabledRAGAlerts":false}', } ); }); - it('calls the non-stream API when assistantStreamingEnabled is true and actionTypeId is gemini and isEnabledKnowledgeBase is false and isEnabledRAGAlerts is true', async () => { + it('calls the stream API when assistantStreamingEnabled is true and actionTypeId is gemini and isEnabledKnowledgeBase is false and isEnabledRAGAlerts is true', async () => { const testProps: FetchConnectorExecuteAction = { ...fetchConnectorArgs, apiConfig: apiConfig.gemini, @@ -164,8 +164,8 @@ describe('API tests', () => { expect(mockHttp.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/actions/connector/foo/_execute', { - ...staticDefaults, - body: '{"message":"This is a test","subAction":"invokeAI","conversationId":"test","actionTypeId":".gemini","replacements":{},"isEnabledKnowledgeBase":false,"isEnabledRAGAlerts":true}', + ...streamingDefaults, + body: '{"message":"This is a test","subAction":"invokeStream","conversationId":"test","actionTypeId":".gemini","replacements":{},"isEnabledKnowledgeBase":false,"isEnabledRAGAlerts":true}', } ); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx index fa12841a96152..a554324515ad6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx @@ -64,13 +64,7 @@ export const fetchConnectorExecuteAction = async ({ traceOptions, }: FetchConnectorExecuteAction): Promise => { // TODO add streaming support for gemini with langchain on - const isStream = - assistantStreamingEnabled && - (apiConfig.actionTypeId === '.gen-ai' || - apiConfig.actionTypeId === '.bedrock' || - // TODO add streaming support for gemini with langchain on - // tracked here: https://github.com/elastic/security-team/issues/7363 - (apiConfig.actionTypeId === '.gemini' && !isEnabledRAGAlerts && !isEnabledKnowledgeBase)); + const isStream = assistantStreamingEnabled; const optionalRequestParams = getOptionalRequestParams({ isEnabledRAGAlerts, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx index b93c166a9c5d7..293993e82fde6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.tsx @@ -30,6 +30,7 @@ export interface Props { const actionTypeKey = { bedrock: '.bedrock', openai: '.gen-ai', + gemini: '.gemini', }; export const useLoadConnectors = ({ @@ -44,7 +45,9 @@ export const useLoadConnectors = ({ (acc: AIConnector[], connector) => [ ...acc, ...(!connector.isMissingSecrets && - [actionTypeKey.bedrock, actionTypeKey.openai].includes(connector.actionTypeId) + [actionTypeKey.bedrock, actionTypeKey.openai, actionTypeKey.gemini].includes( + connector.actionTypeId + ) ? [ { ...connector, diff --git a/x-pack/packages/kbn-langchain/server/index.ts b/x-pack/packages/kbn-langchain/server/index.ts index 12c32c86563a8..1d52159951809 100644 --- a/x-pack/packages/kbn-langchain/server/index.ts +++ b/x-pack/packages/kbn-langchain/server/index.ts @@ -9,10 +9,12 @@ import { ActionsClientChatOpenAI } from './language_models/chat_openai'; import { ActionsClientLlm } from './language_models/llm'; import { ActionsClientSimpleChatModel } from './language_models/simple_chat_model'; import { parseBedrockStream } from './utils/bedrock'; +import { parseGeminiResponse } from './utils/gemini'; import { getDefaultArguments } from './language_models/constants'; export { parseBedrockStream, + parseGeminiResponse, getDefaultArguments, ActionsClientChatOpenAI, ActionsClientLlm, diff --git a/x-pack/packages/kbn-langchain/server/language_models/constants.ts b/x-pack/packages/kbn-langchain/server/language_models/constants.ts index d4d38d172f975..be9866023120e 100644 --- a/x-pack/packages/kbn-langchain/server/language_models/constants.ts +++ b/x-pack/packages/kbn-langchain/server/language_models/constants.ts @@ -11,6 +11,10 @@ export const getDefaultArguments = (llmType?: string, temperature?: number, stop temperature: temperature ?? DEFAULT_BEDROCK_TEMPERATURE, stopSequences: stop ?? DEFAULT_BEDROCK_STOP_SEQUENCES, } + : llmType === 'gemini' + ? { + temperature: temperature ?? DEFAULT_GEMINI_TEMPERATURE, + } : { n: 1, stop: stop ?? null, temperature: temperature ?? DEFAULT_OPEN_AI_TEMPERATURE }; export const DEFAULT_OPEN_AI_TEMPERATURE = 0.2; @@ -19,4 +23,5 @@ export const DEFAULT_OPEN_AI_TEMPERATURE = 0.2; export const DEFAULT_OPEN_AI_MODEL = 'gpt-4'; const DEFAULT_BEDROCK_TEMPERATURE = 0; const DEFAULT_BEDROCK_STOP_SEQUENCES = ['\n\nHuman:', '\nObservation:']; +const DEFAULT_GEMINI_TEMPERATURE = 0; export const DEFAULT_TIMEOUT = 180000; diff --git a/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.test.ts b/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.test.ts index 6a11466f9faa0..a9d2142fc3963 100644 --- a/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.test.ts +++ b/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.test.ts @@ -14,6 +14,7 @@ import { mockActionResponse } from './mocks'; import { BaseMessage } from '@langchain/core/messages'; import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager'; import { parseBedrockStream } from '../utils/bedrock'; +import { parseGeminiStream } from '../utils/gemini'; const connectorId = 'mock-connector-id'; @@ -94,6 +95,7 @@ const defaultArgs = { streaming: false, }; jest.mock('../utils/bedrock'); +jest.mock('../utils/gemini'); describe('ActionsClientSimpleChatModel', () => { beforeEach(() => { @@ -216,6 +218,7 @@ describe('ActionsClientSimpleChatModel', () => { describe('_call streaming: true', () => { beforeEach(() => { (parseBedrockStream as jest.Mock).mockResolvedValue(mockActionResponse.message); + (parseGeminiStream as jest.Mock).mockResolvedValue(mockActionResponse.message); }); it('returns the expected content when _call is invoked with streaming and llmType is Bedrock', async () => { const actionsClientSimpleChatModel = new ActionsClientSimpleChatModel({ @@ -238,7 +241,7 @@ describe('ActionsClientSimpleChatModel', () => { it('returns the expected content when _call is invoked with streaming and llmType is Gemini', async () => { const actionsClientSimpleChatModel = new ActionsClientSimpleChatModel({ ...defaultArgs, - actions: mockActions, + actions: mockStreamActions, llmType: 'gemini', streaming: true, }); @@ -248,8 +251,8 @@ describe('ActionsClientSimpleChatModel', () => { callOptions, callRunManager ); - const subAction = mockExecute.mock.calls[0][0].params.subAction; - expect(subAction).toEqual('invokeAI'); + const subAction = mockStreamExecute.mock.calls[0][0].params.subAction; + expect(subAction).toEqual('invokeStream'); expect(result).toEqual(mockActionResponse.message); }); diff --git a/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.ts b/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.ts index 9f6f3a331a7fb..161e3601ee3ae 100644 --- a/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.ts +++ b/x-pack/packages/kbn-langchain/server/language_models/simple_chat_model.ts @@ -17,6 +17,7 @@ import { KibanaRequest } from '@kbn/core-http-server'; import { v4 as uuidv4 } from 'uuid'; import { get } from 'lodash/fp'; import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager'; +import { parseGeminiStream } from '../utils/gemini'; import { parseBedrockStream } from '../utils/bedrock'; import { getDefaultArguments } from './constants'; @@ -75,8 +76,7 @@ export class ActionsClientSimpleChatModel extends SimpleChatModel { this.llmType = llmType ?? 'ActionsClientSimpleChatModel'; this.model = model; this.temperature = temperature; - // only enable streaming for bedrock - this.streaming = streaming && llmType === 'bedrock'; + this.streaming = streaming; } _llmType() { @@ -154,7 +154,6 @@ export class ActionsClientSimpleChatModel extends SimpleChatModel { return content; // per the contact of _call, return a string } - // Bedrock streaming const readable = get('data', actionResult) as Readable; if (typeof readable?.read !== 'function') { @@ -182,13 +181,9 @@ export class ActionsClientSimpleChatModel extends SimpleChatModel { } } }; + const streamParser = this.llmType === 'bedrock' ? parseBedrockStream : parseGeminiStream; - const parsed = await parseBedrockStream( - readable, - this.#logger, - this.#signal, - handleLLMNewToken - ); + const parsed = await streamParser(readable, this.#logger, this.#signal, handleLLMNewToken); return parsed; // per the contact of _call, return a string } diff --git a/x-pack/packages/kbn-langchain/server/utils/bedrock.ts b/x-pack/packages/kbn-langchain/server/utils/bedrock.ts index 4b0b6ca245ff2..08e884ef01da2 100644 --- a/x-pack/packages/kbn-langchain/server/utils/bedrock.ts +++ b/x-pack/packages/kbn-langchain/server/utils/bedrock.ts @@ -6,17 +6,10 @@ */ import { finished } from 'stream/promises'; -import { Readable } from 'stream'; import { Logger } from '@kbn/core/server'; import { EventStreamCodec } from '@smithy/eventstream-codec'; import { fromUtf8, toUtf8 } from '@smithy/util-utf8'; - -type StreamParser = ( - responseStream: Readable, - logger: Logger, - abortSignal?: AbortSignal, - tokenHandler?: (token: string) => void -) => Promise; +import { StreamParser } from './types'; export const parseBedrockStream: StreamParser = async ( responseStream, diff --git a/x-pack/packages/kbn-langchain/server/utils/gemini.test.ts b/x-pack/packages/kbn-langchain/server/utils/gemini.test.ts new file mode 100644 index 0000000000000..3fcdb87b24551 --- /dev/null +++ b/x-pack/packages/kbn-langchain/server/utils/gemini.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Readable } from 'stream'; +import { parseGeminiStream, parseGeminiResponse } from './gemini'; +import { loggerMock } from '@kbn/logging-mocks'; + +describe('parseGeminiStream', () => { + const mockLogger = loggerMock.create(); + let mockStream: Readable; + + beforeEach(() => { + jest.clearAllMocks(); + mockStream = new Readable({ + read() {}, + }); + }); + + it('should parse the stream correctly', async () => { + const data = + 'data: {"candidates":[{"content":{"role":"system","parts":[{"text":"Hello"}]},"finishReason":"stop","safetyRatings":[{"category":"safe","probability":"low"}]}],"usageMetadata":{"promptTokenCount":10,"candidatesTokenCount":10,"totalTokenCount":20}}\n'; + mockStream.push(data); + mockStream.push(null); + + const result = await parseGeminiStream(mockStream, mockLogger); + expect(result).toBe('Hello'); + }); + + it('should handle abort signal correctly', async () => { + const abortSignal = new AbortController().signal; + setTimeout(() => { + abortSignal.dispatchEvent(new Event('abort')); + }, 100); + + const result = parseGeminiStream(mockStream, mockLogger, abortSignal); + + await expect(result).resolves.toBe(''); + expect(mockLogger.info).toHaveBeenCalledWith('Bedrock stream parsing was aborted.'); + }); + + it('should call tokenHandler with correct tokens', async () => { + const data = + 'data: {"candidates":[{"content":{"role":"system","parts":[{"text":"Hello world"}]},"finishReason":"stop","safetyRatings":[{"category":"safe","probability":"low"}]}],"usageMetadata":{"promptTokenCount":10,"candidatesTokenCount":10,"totalTokenCount":20}}\n'; + mockStream.push(data); + mockStream.push(null); + + const tokenHandler = jest.fn(); + await parseGeminiStream(mockStream, mockLogger, undefined, tokenHandler); + + expect(tokenHandler).toHaveBeenCalledWith('Hello '); + expect(tokenHandler).toHaveBeenCalledWith('world '); + }); + + it('should handle stream error correctly', async () => { + const error = new Error('Stream error'); + const resultPromise = parseGeminiStream(mockStream, mockLogger); + + mockStream.emit('error', error); + + await expect(resultPromise).rejects.toThrow('Stream error'); + }); +}); + +describe('parseGeminiResponse', () => { + it('should parse response correctly', () => { + const response = + 'data: {"candidates":[{"content":{"role":"system","parts":[{"text":"Hello"}]},"finishReason":"stop","safetyRatings":[{"category":"safe","probability":"low"}]}],"usageMetadata":{"promptTokenCount":10,"candidatesTokenCount":10,"totalTokenCount":20}}\n'; + const result = parseGeminiResponse(response); + expect(result).toBe('Hello'); + }); + + it('should ignore lines that do not start with data: ', () => { + const response = + 'invalid line\ndata: {"candidates":[{"content":{"role":"system","parts":[{"text":"Hello"}]},"finishReason":"stop","safetyRatings":[{"category":"safe","probability":"low"}]}],"usageMetadata":{"promptTokenCount":10,"candidatesTokenCount":10,"totalTokenCount":20}}\n'; + const result = parseGeminiResponse(response); + expect(result).toBe('Hello'); + }); + + it('should ignore lines that end with [DONE]', () => { + const response = + 'data: {"candidates":[{"content":{"role":"system","parts":[{"text":"Hello"}]},"finishReason":"stop","safetyRatings":[{"category":"safe","probability":"low"}]}],"usageMetadata":{"promptTokenCount":10,"candidatesTokenCount":10,"totalTokenCount":20}}\ndata: [DONE]'; + const result = parseGeminiResponse(response); + expect(result).toBe('Hello'); + }); +}); diff --git a/x-pack/packages/kbn-langchain/server/utils/gemini.ts b/x-pack/packages/kbn-langchain/server/utils/gemini.ts new file mode 100644 index 0000000000000..68fa4c0363e13 --- /dev/null +++ b/x-pack/packages/kbn-langchain/server/utils/gemini.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { StreamParser } from './types'; + +export const parseGeminiStream: StreamParser = async ( + stream, + logger, + abortSignal, + tokenHandler +) => { + let responseBody = ''; + stream.on('data', (chunk) => { + const decoded = chunk.toString(); + const parsed = parseGeminiResponse(decoded); + if (tokenHandler) { + const splitByQuotes = parsed.split(`"`); + splitByQuotes.forEach((chunkk, index) => { + // add quote back on except for last chunk + const splitBySpace = `${chunkk}${index === splitByQuotes.length - 1 ? '' : '"'}`.split(` `); + + for (const char of splitBySpace) { + tokenHandler(`${char} `); + } + }); + } + responseBody += parsed; + }); + return new Promise((resolve, reject) => { + stream.on('end', () => { + resolve(responseBody); + }); + stream.on('error', (err) => { + reject(err); + }); + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + logger.info('Bedrock stream parsing was aborted.'); + stream.destroy(); + resolve(responseBody); + }); + } + }); +}; + +/** Parse Gemini stream response body */ +export const parseGeminiResponse = (responseBody: string) => { + return responseBody + .split('\n') + .filter((line) => line.startsWith('data: ') && !line.endsWith('[DONE]')) + .map((line) => JSON.parse(line.replace('data: ', ''))) + .filter( + ( + line + ): line is { + candidates: Array<{ + content: { role: string; parts: Array<{ text: string }> }; + finishReason: string; + safetyRatings: Array<{ category: string; probability: string }>; + }>; + usageMetadata: { + promptTokenCount: number; + candidatesTokenCount: number; + totalTokenCount: number; + }; + } => 'candidates' in line + ) + .reduce((prev, line) => { + if (line.candidates[0] && line.candidates[0].content) { + const parts = line.candidates[0].content.parts; + const text = parts.map((part) => part.text).join(''); + return prev + text; + } + return prev; + }, ''); +}; diff --git a/x-pack/packages/kbn-langchain/server/utils/types.ts b/x-pack/packages/kbn-langchain/server/utils/types.ts new file mode 100644 index 0000000000000..d88adb4045e87 --- /dev/null +++ b/x-pack/packages/kbn-langchain/server/utils/types.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Readable } from 'stream'; +import { Logger } from '@kbn/logging'; + +export type StreamParser = ( + responseStream: Readable, + logger: Logger, + abortSignal?: AbortSignal, + tokenHandler?: (token: string) => void +) => Promise; + +export interface GeminiResponseSchema { + candidates: Candidate[]; + usageMetadata: { + promptTokenCount: number; + candidatesTokenCount: number; + totalTokenCount: number; + }; +} +interface Part { + text: string; +} + +interface Candidate { + content: Content; + finishReason: string; +} + +interface Content { + role: string; + parts: Part[]; +} diff --git a/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap b/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap index f431271ad42f9..84f1c1966747b 100644 --- a/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap +++ b/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap @@ -3037,6 +3037,49 @@ Object { ], "type": "any", }, + "stopSequences": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "array", + }, + "temperature": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "number", + }, "timeout": Object { "flags": Object { "default": [Function], @@ -3155,6 +3198,49 @@ Object { ], "type": "any", }, + "stopSequences": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "array", + }, + "temperature": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "number", + }, "timeout": Object { "flags": Object { "default": [Function], @@ -3179,6 +3265,254 @@ Object { `; exports[`Connector type config checks detect connector type changes for: .gemini 4`] = ` +Object { + "flags": Object { + "default": Object { + "special": "deep", + }, + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "messages": Object { + "flags": Object { + "error": [Function], + }, + "metas": Array [ + Object { + "x-oas-any-type": true, + }, + ], + "type": "any", + }, + "model": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + "signal": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-any-type": true, + }, + Object { + "x-oas-optional": true, + }, + ], + "type": "any", + }, + "stopSequences": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "array", + }, + "temperature": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "number", + }, + "timeout": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "number", + }, + }, + "preferences": Object { + "stripUnknown": Object { + "objects": false, + }, + }, + "type": "object", +} +`; + +exports[`Connector type config checks detect connector type changes for: .gemini 5`] = ` +Object { + "flags": Object { + "default": Object { + "special": "deep", + }, + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "messages": Object { + "flags": Object { + "error": [Function], + }, + "metas": Array [ + Object { + "x-oas-any-type": true, + }, + ], + "type": "any", + }, + "model": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + "signal": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-any-type": true, + }, + Object { + "x-oas-optional": true, + }, + ], + "type": "any", + }, + "stopSequences": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "array", + }, + "temperature": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "number", + }, + "timeout": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "number", + }, + }, + "preferences": Object { + "stripUnknown": Object { + "objects": false, + }, + }, + "type": "object", +} +`; + +exports[`Connector type config checks detect connector type changes for: .gemini 6`] = ` Object { "flags": Object { "default": Object { @@ -3256,7 +3590,7 @@ Object { } `; -exports[`Connector type config checks detect connector type changes for: .gemini 5`] = ` +exports[`Connector type config checks detect connector type changes for: .gemini 7`] = ` Object { "flags": Object { "default": Object { @@ -3290,7 +3624,7 @@ Object { } `; -exports[`Connector type config checks detect connector type changes for: .gemini 6`] = ` +exports[`Connector type config checks detect connector type changes for: .gemini 8`] = ` Object { "flags": Object { "default": Object { diff --git a/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.test.ts b/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.test.ts index c3624178046fc..d6c89a35ba7ff 100644 --- a/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.test.ts +++ b/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.test.ts @@ -256,6 +256,7 @@ describe('getGenAiTokenTracking', () => { }) ); }); + it('should return 0s for the total, prompt, and completion token counts when given an invalid OpenAI async iterator response', async () => { const actionTypeId = '.gen-ai'; const result = { @@ -360,6 +361,37 @@ describe('getGenAiTokenTracking', () => { expect(logger.error).toHaveBeenCalled(); }); + it('should return the total, prompt, and completion token counts when given a valid Gemini streamed response', async () => { + const actionTypeId = '.gemini'; + const result = { + actionId: '123', + status: 'ok' as const, + data: { + usageMetadata: { + promptTokenCount: 50, + candidatesTokenCount: 50, + totalTokenCount: 100, + }, + }, + }; + const validatedParams = { + subAction: 'invokeStream', + }; + + const tokenTracking = await getGenAiTokenTracking({ + actionTypeId, + logger, + result, + validatedParams, + }); + + expect(tokenTracking).toEqual({ + total_tokens: 100, + prompt_tokens: 50, + completion_tokens: 50, + }); + }); + describe('shouldTrackGenAiToken', () => { it('should be true with OpenAI action', () => { expect(shouldTrackGenAiToken('.gen-ai')).toEqual(true); @@ -367,7 +399,7 @@ describe('getGenAiTokenTracking', () => { it('should be true with bedrock action', () => { expect(shouldTrackGenAiToken('.bedrock')).toEqual(true); }); - it('should be true with Gemini action', () => { + it('should be true with gemini action', () => { expect(shouldTrackGenAiToken('.gemini')).toEqual(true); }); it('should be false with any other action', () => { diff --git a/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.ts b/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.ts index 15c5b234d24bc..41bfa28605f40 100644 --- a/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.ts +++ b/x-pack/plugins/actions/server/lib/gen_ai_token_tracking.ts @@ -16,7 +16,11 @@ import { import { getTokenCountFromBedrockInvoke } from './get_token_count_from_bedrock_invoke'; import { ActionTypeExecutorRawResult } from '../../common'; import { getTokenCountFromOpenAIStream } from './get_token_count_from_openai_stream'; -import { getTokenCountFromInvokeStream, InvokeBody } from './get_token_count_from_invoke_stream'; +import { + getTokenCountFromInvokeStream, + InvokeBody, + parseGeminiStreamForUsageMetadata, +} from './get_token_count_from_invoke_stream'; interface OwnProps { actionTypeId: string; @@ -80,8 +84,37 @@ export const getGenAiTokenTracking = async ({ } } + // this is a streamed Gemini response, using the subAction invokeStream to stream the response as a simple string + if ( + validatedParams.subAction === 'invokeStream' && + result.data instanceof Readable && + actionTypeId === '.gemini' + ) { + try { + const { totalTokenCount, promptTokenCount, candidatesTokenCount } = + await parseGeminiStreamForUsageMetadata({ + responseStream: result.data.pipe(new PassThrough()), + logger, + }); + + return { + total_tokens: totalTokenCount, + prompt_tokens: promptTokenCount, + completion_tokens: candidatesTokenCount, + }; + } catch (e) { + logger.error('Failed to calculate tokens from Invoke Stream subaction streaming response'); + logger.error(e); + // silently fail and null is returned at bottom of fuction + } + } + // this is a streamed OpenAI or Bedrock response, using the subAction invokeStream to stream the response as a simple string - if (validatedParams.subAction === 'invokeStream' && result.data instanceof Readable) { + if ( + validatedParams.subAction === 'invokeStream' && + result.data instanceof Readable && + actionTypeId !== '.gemini' + ) { try { const { total, prompt, completion } = await getTokenCountFromInvokeStream({ responseStream: result.data.pipe(new PassThrough()), diff --git a/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.test.ts b/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.test.ts index dad1785538b2c..3a2cabbb1b0e4 100644 --- a/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.test.ts +++ b/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.test.ts @@ -5,7 +5,10 @@ * 2.0. */ import { Transform } from 'stream'; -import { getTokenCountFromInvokeStream } from './get_token_count_from_invoke_stream'; +import { + getTokenCountFromInvokeStream, + parseGeminiStreamForUsageMetadata, +} from './get_token_count_from_invoke_stream'; import { loggerMock } from '@kbn/logging-mocks'; import { EventStreamCodec } from '@smithy/eventstream-codec'; import { fromUtf8, toUtf8 } from '@smithy/util-utf8'; @@ -57,8 +60,29 @@ describe('getTokenCountFromInvokeStream', () => { ], }; + const geminiChunk = { + candidates: [ + { + content: { + role: 'model', + parts: [ + { + text: '. I be no real-life pirate, but I be mighty good at pretendin!', + }, + ], + }, + }, + ], + usageMetadata: { + promptTokenCount: 23, + candidatesTokenCount: 50, + totalTokenCount: 73, + }, + }; + const PROMPT_TOKEN_COUNT = 34; const COMPLETION_TOKEN_COUNT = 2; + describe('OpenAI stream', () => { beforeEach(() => { stream = createStreamMock(); @@ -200,6 +224,24 @@ describe('getTokenCountFromInvokeStream', () => { }); }); }); + describe('Gemini stream', () => { + beforeEach(() => { + stream = createStreamMock(); + stream.write(`data: ${JSON.stringify(geminiChunk)}`); + }); + + it('counts the prompt, completion & total tokens for Gemini response', async () => { + stream.complete(); + const tokens = await parseGeminiStreamForUsageMetadata({ + responseStream: stream.transform, + logger, + }); + + expect(tokens.promptTokenCount).toBe(23); + expect(tokens.candidatesTokenCount).toBe(50); + expect(tokens.totalTokenCount).toBe(73); + }); + }); }); function encodeBedrockResponse(completion: string | Record) { diff --git a/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.ts b/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.ts index 7fd05aa8c500d..604e623699136 100644 --- a/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.ts +++ b/x-pack/plugins/actions/server/lib/get_token_count_from_invoke_stream.ts @@ -20,6 +20,12 @@ export interface InvokeBody { signal?: AbortSignal; } +interface UsageMetadata { + promptTokenCount: number; + candidatesTokenCount: number; + totalTokenCount: number; +} + /** * Takes the OpenAI and Bedrock `invokeStream` sub action response stream and the request messages array as inputs. * Uses gpt-tokenizer encoding to calculate the number of tokens in the prompt and completion parts of the response stream @@ -130,6 +136,64 @@ const parseOpenAIStream: StreamParser = async (responseStream, logger, signal) = return parseOpenAIResponse(responseBody); }; +export const parseGeminiStreamForUsageMetadata = async ({ + responseStream, + logger, +}: { + responseStream: Readable; + logger: Logger; +}): Promise => { + let responseBody = ''; + + const onData = (chunk: Buffer) => { + responseBody += chunk.toString(); + }; + + responseStream.on('data', onData); + + return new Promise((resolve, reject) => { + responseStream.on('end', () => { + resolve(parseGeminiUsageMetadata(responseBody)); + }); + responseStream.on('error', (err) => { + logger.error('An error occurred while calculating streaming response tokens'); + reject(err); + }); + }); +}; + +/** Parse Gemini stream response body */ +const parseGeminiUsageMetadata = (responseBody: string): UsageMetadata => { + const parsedLines = responseBody + .split('\n') + .filter((line) => line.startsWith('data: ') && !line.endsWith('[DONE]')) + .map((line) => JSON.parse(line.replace('data: ', ''))); + + parsedLines + .filter( + ( + line + ): line is { + candidates: Array<{ + content: { role: string; parts: Array<{ text: string }> }; + finishReason: string; + safetyRatings: Array<{ category: string; probability: string }>; + }>; + } => 'candidates' in line + ) + .reduce((prev, line) => { + const parts = line.candidates[0].content?.parts; + const chunkText = parts?.map((part) => part.text).join(''); + return prev + chunkText; + }, ''); + + // Extract usage metadata from the last chunk + const lastChunk = parsedLines[parsedLines.length - 1]; + const usageMetadata = 'usageMetadata' in lastChunk ? lastChunk.usageMetadata : null; + + return usageMetadata; +}; + /** * Parses a Bedrock buffer from an array of chunks. * diff --git a/x-pack/plugins/elastic_assistant/server/lib/parse_stream.test.ts b/x-pack/plugins/elastic_assistant/server/lib/parse_stream.test.ts index 76b29fc115b4b..959bb51c40949 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/parse_stream.test.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/parse_stream.test.ts @@ -99,6 +99,46 @@ describe('handleStreamStorage', () => { it('saves the error message on a failed streaming event', async () => { const tokenPromise = handleStreamStorage({ ...defaultProps, actionTypeId: '.bedrock' }); + stream.fail(); + await expect(tokenPromise).resolves.not.toThrow(); + expect(onMessageSent).toHaveBeenCalledWith( + `An error occurred while streaming the response:\n\nStream failed` + ); + }); + }); + describe('Gemini stream', () => { + beforeEach(() => { + stream = createStreamMock(); + const payload = { + candidates: [ + { + content: { + parts: [ + { + text: 'Single.', + }, + ], + }, + }, + ], + }; + stream.write(`data: ${JSON.stringify(payload)}`); + defaultProps = { + responseStream: stream.transform, + actionTypeId: '.gemini', + onMessageSent, + logger: mockLogger, + }; + }); + + it('saves the final string successful streaming event', async () => { + stream.complete(); + await handleStreamStorage(defaultProps); + expect(onMessageSent).toHaveBeenCalledWith('Single.'); + }); + it('saves the error message on a failed streaming event', async () => { + const tokenPromise = handleStreamStorage(defaultProps); + stream.fail(); await expect(tokenPromise).resolves.not.toThrow(); expect(onMessageSent).toHaveBeenCalledWith( diff --git a/x-pack/plugins/elastic_assistant/server/lib/parse_stream.ts b/x-pack/plugins/elastic_assistant/server/lib/parse_stream.ts index e42ce6e3651fb..55be80cbb522d 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/parse_stream.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/parse_stream.ts @@ -7,7 +7,7 @@ import { Readable } from 'stream'; import { Logger } from '@kbn/core/server'; -import { parseBedrockStream } from '@kbn/langchain/server'; +import { parseBedrockStream, parseGeminiResponse } from '@kbn/langchain/server'; type StreamParser = ( responseStream: Readable, @@ -30,7 +30,12 @@ export const handleStreamStorage = async ({ logger: Logger; }): Promise => { try { - const parser = actionTypeId === '.bedrock' ? parseBedrockStream : parseOpenAIStream; + const parser = + actionTypeId === '.bedrock' + ? parseBedrockStream + : actionTypeId === '.gemini' + ? parseGeminiStream + : parseOpenAIStream; const parsedResponse = await parser(responseStream, logger, abortSignal); if (onMessageSent) { onMessageSent(parsedResponse); @@ -87,3 +92,25 @@ const parseOpenAIResponse = (responseBody: string) => const msg = line.choices[0].delta; return prev + (msg.content || ''); }, ''); + +export const parseGeminiStream: StreamParser = async (stream, logger, abortSignal) => { + let responseBody = ''; + stream.on('data', (chunk) => { + responseBody += chunk.toString(); + }); + return new Promise((resolve, reject) => { + stream.on('end', () => { + resolve(parseGeminiResponse(responseBody)); + }); + stream.on('error', (err) => { + reject(err); + }); + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + stream.destroy(); + logger.info('Gemini stream parsing was aborted.'); + resolve(parseGeminiResponse(responseBody)); + }); + } + }); +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/utils.ts b/x-pack/plugins/elastic_assistant/server/routes/utils.ts index 243befcb19271..324d2fefa46b9 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/utils.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/utils.ts @@ -170,6 +170,7 @@ export const getLlmType = (actionTypeId: string): string | undefined => { const llmTypeDictionary: Record = { [`.gen-ai`]: `openai`, [`.bedrock`]: `bedrock`, + [`.gemini`]: `gemini`, }; return llmTypeDictionary[actionTypeId]; }; diff --git a/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.test.ts b/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.test.ts index 07f38251d3873..f4257e12e1587 100644 --- a/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.test.ts +++ b/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.test.ts @@ -398,6 +398,147 @@ describe('getStreamObservable', () => { error: (err) => done(err), }); }); + it('should emit loading state and chunks for Gemini', (done) => { + const chunk1 = `data: {"candidates": [{"content":{"role":"model","parts":[{"text":"My"}]}}]}\rdata: {"candidates": [{"content":{"role":"model","parts":[{"text":" new"}]}}]}`; + const chunk2 = `\rdata: {"candidates": [{"content": {"role": "model","parts": [{"text": " message"}]},"finishReason": "STOP"}],"usageMetadata": {"promptTokenCount": 23,"candidatesTokenCount": 50,"totalTokenCount": 73}}`; + const completeSubject = new Subject(); + const expectedStates: PromptObservableState[] = [ + { chunks: [], loading: true }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My ', + loading: true, + }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My ', + loading: true, + }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My new ', + loading: true, + }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My new message', + loading: false, + }, + ]; + + mockReader.read + .mockResolvedValueOnce({ + done: false, + value: new Uint8Array(new TextEncoder().encode(chunk1)), + }) + .mockResolvedValueOnce({ + done: false, + value: new Uint8Array(new TextEncoder().encode(chunk2)), + }) + .mockResolvedValueOnce({ + done: false, + value: new Uint8Array(new TextEncoder().encode('')), + }) + .mockResolvedValue({ + done: true, + }); + + const source = getStreamObservable({ + ...defaultProps, + actionTypeId: '.gemini', + }); + const emittedStates: PromptObservableState[] = []; + + source.subscribe({ + next: (state) => { + return emittedStates.push(state); + }, + complete: () => { + expect(emittedStates).toEqual(expectedStates); + done(); + + completeSubject.subscribe({ + next: () => { + expect(setLoading).toHaveBeenCalledWith(false); + expect(typedReader.cancel).toHaveBeenCalled(); + done(); + }, + }); + }, + error: (err) => done(err), + }); + }); + + it('should emit loading state and chunks for partial response Gemini', (done) => { + const chunk1 = `data: {"candidates": [{"content":{"role":"model","parts":[{"text":"My"}]}}]}\rdata: {"candidates": [{"content":{"role":"model","parts":[{"text":" new"}]}}]}`; + const chunk2 = `\rdata: {"candidates": [{"content": {"role": "model","parts": [{"text": " message"}]},"finishReason": "STOP"}],"usageMetadata": {"promptTokenCount": 23,"candidatesTokenCount": 50,"totalTokenCount": 73}}`; + const completeSubject = new Subject(); + const expectedStates: PromptObservableState[] = [ + { chunks: [], loading: true }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My ', + loading: true, + }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My ', + loading: true, + }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My new ', + loading: true, + }, + { + chunks: ['My ', ' ', 'new ', ' message'], + message: 'My new message', + loading: false, + }, + ]; + + mockReader.read + .mockResolvedValueOnce({ + done: false, + value: new Uint8Array(new TextEncoder().encode(chunk1)), + }) + .mockResolvedValueOnce({ + done: false, + value: new Uint8Array(new TextEncoder().encode(chunk2)), + }) + .mockResolvedValueOnce({ + done: false, + value: new Uint8Array(new TextEncoder().encode('')), + }) + .mockResolvedValue({ + done: true, + }); + + const source = getStreamObservable({ + ...defaultProps, + actionTypeId: '.gemini', + }); + const emittedStates: PromptObservableState[] = []; + + source.subscribe({ + next: (state) => { + return emittedStates.push(state); + }, + complete: () => { + expect(emittedStates).toEqual(expectedStates); + done(); + + completeSubject.subscribe({ + next: () => { + expect(setLoading).toHaveBeenCalledWith(false); + expect(typedReader.cancel).toHaveBeenCalled(); + done(); + }, + }); + }, + error: (err) => done(err), + }); + }); it('should stream errors when reader contains errors', (done) => { const completeSubject = new Subject(); diff --git a/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.ts b/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.ts index 2ee9b2aa1e3d4..338ed7b661f84 100644 --- a/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.ts +++ b/x-pack/plugins/security_solution/public/assistant/get_comments/stream/stream_observable.ts @@ -19,6 +19,30 @@ interface StreamObservable { reader: ReadableStreamDefaultReader; setLoading: Dispatch>; } + +interface ResponseSchema { + candidates: Candidate[]; + usageMetadata: { + promptTokenCount: number; + candidatesTokenCount: number; + totalTokenCount: number; + }; +} + +interface Part { + text: string; +} + +interface Candidate { + content: Content; + finishReason: string; +} + +interface Content { + role: string; + parts: Part[]; +} + /** * Returns an Observable that reads data from a ReadableStream and emits values representing the state of the data processing. * @@ -44,9 +68,10 @@ export const getStreamObservable = ({ let openAIBuffer: string = ''; // Initialize an empty string to store the LangChain buffer. let langChainBuffer: string = ''; - // Initialize an empty Uint8Array to store the Bedrock concatenated buffer. let bedrockBuffer: Uint8Array = new Uint8Array(0); + // Initialize an empty string to store the Gemini buffer. + let geminiBuffer: string = ''; // read data from LangChain stream function readLangChain() { @@ -203,6 +228,54 @@ export const getStreamObservable = ({ }); } + // read data from Gemini stream + function readGemini() { + reader + .read() + .then(({ done, value }: { done: boolean; value?: Uint8Array }) => { + try { + if (done) { + if (geminiBuffer) { + chunks.push(getGeminiChunks([geminiBuffer])[0]); + } + observer.next({ + chunks, + message: chunks.join(''), + loading: false, + }); + observer.complete(); + return; + } + + const decoded = decoder.decode(value, { stream: true }); + const lines = decoded.split('\r'); + lines[0] = geminiBuffer + lines[0]; + geminiBuffer = lines.pop() || ''; + + const nextChunks = getGeminiChunks(lines); + + nextChunks.forEach((chunk: string) => { + const splitBySpace = chunk.split(' '); + for (const word of splitBySpace) { + chunks.push(`${word} `); + observer.next({ + chunks, + message: chunks.join(''), + loading: true, + }); + } + }); + } catch (err) { + observer.error(err); + return; + } + readGemini(); + }) + .catch((err) => { + observer.error(err); + }); + } + // this should never actually happen function badConnector() { observer.next({ @@ -215,6 +288,7 @@ export const getStreamObservable = ({ if (isEnabledLangChain) readLangChain(); else if (actionTypeId === '.bedrock') readBedrock(); else if (actionTypeId === '.gen-ai') readOpenAI(); + else if (actionTypeId === '.gemini') readGemini(); else badConnector(); return () => { @@ -292,4 +366,23 @@ const getLangChainChunks = (lines: string[]): string[] => return acc; }, []); +/** + * Parses an Gemini response from a string. + * @param lines + * @returns {string[]} - Parsed string array from the Gemini response. + */ +const getGeminiChunks = (lines: string[]): string[] => { + return lines + .filter((str) => !!str && str !== '[DONE]') + .map((line) => { + try { + const newLine = line.replaceAll('data: ', ''); + const geminiResponse: ResponseSchema = JSON.parse(newLine); + return geminiResponse.candidates[0]?.content.parts.map((part) => part.text).join('') ?? ''; + } catch (err) { + return ''; + } + }); +}; + export const getPlaceholderObservable = () => new Observable(); diff --git a/x-pack/plugins/stack_connectors/common/gemini/constants.ts b/x-pack/plugins/stack_connectors/common/gemini/constants.ts index 2df2e4f635e33..e0c1c6f56c65a 100644 --- a/x-pack/plugins/stack_connectors/common/gemini/constants.ts +++ b/x-pack/plugins/stack_connectors/common/gemini/constants.ts @@ -18,6 +18,8 @@ export enum SUB_ACTION { RUN = 'run', DASHBOARD = 'getDashboard', TEST = 'test', + INVOKE_AI = 'invokeAI', + INVOKE_STREAM = 'invokeStream', } export const DEFAULT_TOKEN_LIMIT = 8192; diff --git a/x-pack/plugins/stack_connectors/common/gemini/schema.ts b/x-pack/plugins/stack_connectors/common/gemini/schema.ts index aa29f92916db9..91b523ef4853b 100644 --- a/x-pack/plugins/stack_connectors/common/gemini/schema.ts +++ b/x-pack/plugins/stack_connectors/common/gemini/schema.ts @@ -24,6 +24,8 @@ export const RunActionParamsSchema = schema.object({ model: schema.maybe(schema.string()), signal: schema.maybe(schema.any()), timeout: schema.maybe(schema.number()), + temperature: schema.maybe(schema.number()), + stopSequences: schema.maybe(schema.arrayOf(schema.string())), }); export const RunApiResponseSchema = schema.object({ @@ -50,6 +52,28 @@ export const RunActionResponseSchema = schema.object( { unknowns: 'ignore' } ); +export const InvokeAIActionParamsSchema = schema.object({ + messages: schema.any(), + model: schema.maybe(schema.string()), + temperature: schema.maybe(schema.number()), + stopSequences: schema.maybe(schema.arrayOf(schema.string())), + signal: schema.maybe(schema.any()), + timeout: schema.maybe(schema.number()), +}); + +export const InvokeAIActionResponseSchema = schema.object({ + message: schema.string(), + usageMetadata: schema.maybe( + schema.object({ + promptTokenCount: schema.number(), + candidatesTokenCount: schema.number(), + totalTokenCount: schema.number(), + }) + ), +}); + +export const StreamingResponseSchema = schema.any(); + export const DashboardActionParamsSchema = schema.object({ dashboardId: schema.string(), }); diff --git a/x-pack/plugins/stack_connectors/common/gemini/types.ts b/x-pack/plugins/stack_connectors/common/gemini/types.ts index 12d3ed4a6b1c4..bc9a96ebdfdd7 100644 --- a/x-pack/plugins/stack_connectors/common/gemini/types.ts +++ b/x-pack/plugins/stack_connectors/common/gemini/types.ts @@ -14,6 +14,9 @@ import { RunActionParamsSchema, RunActionResponseSchema, RunApiResponseSchema, + InvokeAIActionParamsSchema, + InvokeAIActionResponseSchema, + StreamingResponseSchema, } from './schema'; export type Config = TypeOf; @@ -23,3 +26,6 @@ export type RunApiResponse = TypeOf; export type RunActionResponse = TypeOf; export type DashboardActionParams = TypeOf; export type DashboardActionResponse = TypeOf; +export type InvokeAIActionParams = TypeOf; +export type InvokeAIActionResponse = TypeOf; +export type StreamingResponse = TypeOf; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/gemini/logo.tsx b/x-pack/plugins/stack_connectors/public/connector_types/gemini/logo.tsx index dd09c31fb7079..17da9f085e974 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/gemini/logo.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/gemini/logo.tsx @@ -9,25 +9,15 @@ import React from 'react'; import { LogoProps } from '../types'; const Logo = (props: LogoProps) => ( - + + - - - - - - - ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts index af5fdc8cb781f..ed825d9aecbf3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts @@ -11,7 +11,10 @@ import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.moc import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; -import { RunApiResponseSchema } from '../../../common/gemini/schema'; +import { RunApiResponseSchema, StreamingResponseSchema } from '../../../common/gemini/schema'; +import { DEFAULT_GEMINI_MODEL } from '../../../common/gemini/constants'; +import { AxiosError } from 'axios'; +import { Transform } from 'stream'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); jest.mock('@kbn/actions-plugin/server/sub_action_framework/helpers/validators', () => ({ @@ -28,14 +31,27 @@ let mockRequest: jest.Mock; describe('GeminiConnector', () => { const defaultResponse = { data: { - candidates: [{ content: { parts: [{ text: 'Paris' }] } }], - usageMetadata: { totalTokens: 0, promptTokens: 0, completionTokens: 0 }, + candidates: [{ content: { role: 'model', parts: [{ text: 'Paris' }] } }], + usageMetadata: { totalTokenCount: 0, promptTokenCount: 0, candidatesTokenCount: 0 }, }, }; + const sampleGeminiBody = { + messages: [ + { + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + }, + ], + }; + const connectorResponse = { completion: 'Paris', - usageMetadata: { totalTokens: 0, promptTokens: 0, completionTokens: 0 }, + usageMetadata: { totalTokenCount: 0, promptTokenCount: 0, candidatesTokenCount: 0 }, }; beforeEach(() => { @@ -50,7 +66,7 @@ describe('GeminiConnector', () => { configurationUtilities: actionsConfigMock.create(), config: { apiUrl: 'https://api.gemini.com', - defaultModel: 'gemini-1.5-pro-preview-0409', + defaultModel: DEFAULT_GEMINI_MODEL, gcpRegion: 'us-central1', gcpProjectID: 'my-project-12345', }, @@ -72,53 +88,228 @@ describe('GeminiConnector', () => { services: actionsMock.createServices(), }); - describe('runApi', () => { - it('should send a formatted request to the API and return the response', async () => { - const runActionParams: RunActionParams = { - body: JSON.stringify({ - messages: [ - { - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], - }, - ], + describe('Gemini', () => { + beforeEach(() => { + // @ts-ignore + connector.request = mockRequest; + }); + + describe('runApi', () => { + it('should send a formatted request to the API and return the response', async () => { + const runActionParams: RunActionParams = { + body: JSON.stringify(sampleGeminiBody), + model: DEFAULT_GEMINI_MODEL, + }; + + const response = await connector.runApi(runActionParams); + + // Assertions + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith({ + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + data: JSON.stringify({ + messages: [ + { + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + timeout: 60000, + responseSchema: RunApiResponseSchema, + signal: undefined, + }); + + expect(response).toEqual(connectorResponse); + }); + }); + + describe('invokeAI', () => { + const aiAssistantBody = { + messages: [ + { + role: 'user', + content: 'What is the capital of France?', + }, + ], + }; + + it('the API call is successful with correct parameters', async () => { + await connector.invokeAI(aiAssistantBody); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith({ + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + responseSchema: RunApiResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - }), - model: 'test-model', + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + signal: undefined, + timeout: 60000, + }); + }); + + it('signal and timeout is properly passed to runApi', async () => { + const signal = jest.fn(); + const timeout = 60000; + await connector.invokeAI({ ...aiAssistantBody, timeout, signal }); + expect(mockRequest).toHaveBeenCalledWith({ + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + responseSchema: RunApiResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, + }, + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + signal, + timeout: 60000, + }); + }); + }); + + describe('invokeStream', () => { + let stream; + beforeEach(() => { + stream = createStreamMock(); + stream.write(new Uint8Array([1, 2, 3])); + mockRequest = jest.fn().mockResolvedValue({ ...defaultResponse, data: stream.transform }); + // @ts-ignore + connector.request = mockRequest; + }); + const aiAssistantBody = { + messages: [ + { + role: 'user', + content: 'What is the capital of France?', + }, + ], }; - const response = await connector.runApi(runActionParams); + it('the API call is successful with correct request parameters', async () => { + await connector.invokeStream(aiAssistantBody); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith({ + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, + }, + }), + responseType: 'stream', + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + signal: undefined, + timeout: 60000, + }); + }); - // Assertions - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/test-model:generateContent', - method: 'post', - data: JSON.stringify({ - messages: [ - { - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], - }, - ], + it('signal and timeout is properly passed to streamApi', async () => { + const signal = jest.fn(); + const timeout = 60000; + await connector.invokeStream({ ...aiAssistantBody, timeout, signal }); + expect(mockRequest).toHaveBeenCalledWith({ + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', - }, - timeout: 60000, - responseSchema: RunApiResponseSchema, - signal: undefined, + }), + responseType: 'stream', + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + signal, + timeout: 60000, + }); + }); + }); + + describe('getResponseErrorMessage', () => { + it('returns an unknown error message', () => { + // @ts-expect-error expects an axios error as the parameter + expect(connector.getResponseErrorMessage({})).toEqual( + `Unexpected API Error: - Unknown error` + ); }); - expect(response).toEqual(connectorResponse); + it('returns the error.message', () => { + // @ts-expect-error expects an axios error as the parameter + expect(connector.getResponseErrorMessage({ message: 'a message' })).toEqual( + `Unexpected API Error: - a message` + ); + }); + + it('returns the error.response.data.error.message', () => { + const err = { + response: { + headers: {}, + status: 404, + statusText: 'Resource Not Found', + data: { + message: 'Resource not found', + }, + }, + } as AxiosError<{ message?: string }>; + expect( + // @ts-expect-error expects an axios error as the parameter + connector.getResponseErrorMessage(err) + ).toEqual(`API Error: Resource Not Found - Resource not found`); + }); }); }); @@ -190,3 +381,21 @@ describe('GeminiConnector', () => { }); }); }); + +function createStreamMock() { + const transform: Transform = new Transform({}); + + return { + write: (data: Uint8Array) => { + transform.push(data); + }, + fail: () => { + transform.emit('error', new Error('Stream failed')); + transform.end(); + }, + transform, + complete: () => { + transform.end(); + }, + }; +} diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts index 61b8834927a48..323b13d3b768e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts @@ -7,23 +7,37 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import { AxiosError, Method } from 'axios'; +import { PassThrough } from 'stream'; +import { IncomingMessage } from 'http'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { getGoogleOAuthJwtAccessToken } from '@kbn/actions-plugin/server/lib/get_gcp_oauth_access_token'; import { Logger } from '@kbn/core/server'; import { ConnectorTokenClientContract } from '@kbn/actions-plugin/server/types'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; -import { RunActionParamsSchema, RunApiResponseSchema } from '../../../common/gemini/schema'; +import { + RunActionParamsSchema, + RunApiResponseSchema, + InvokeAIActionParamsSchema, + StreamingResponseSchema, +} from '../../../common/gemini/schema'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; - import { Config, Secrets, RunActionParams, RunActionResponse, RunApiResponse, + DashboardActionParams, + DashboardActionResponse, + StreamingResponse, + InvokeAIActionParams, + InvokeAIActionResponse, } from '../../../common/gemini/types'; -import { SUB_ACTION, DEFAULT_TIMEOUT_MS } from '../../../common/gemini/constants'; -import { DashboardActionParams, DashboardActionResponse } from '../../../common/gemini/types'; +import { + SUB_ACTION, + DEFAULT_TIMEOUT_MS, + DEFAULT_TOKEN_LIMIT, +} from '../../../common/gemini/constants'; import { DashboardActionParamsSchema } from '../../../common/gemini/schema'; export interface GetAxiosInstanceOpts { @@ -35,6 +49,25 @@ export interface GetAxiosInstanceOpts { configurationUtilities: ActionsConfigurationUtilities; } +/** Interfaces to define Gemini model response type */ + +interface MessagePart { + text: string; +} + +interface MessageContent { + role: string; + parts: MessagePart[]; +} + +interface Payload { + contents: MessageContent[]; + generation_config: { + temperature: number; + maxOutputTokens: number; + }; +} + export class GeminiConnector extends SubActionConnector { private url; private model; @@ -74,6 +107,18 @@ export class GeminiConnector extends SubActionConnector { method: 'runApi', schema: RunActionParamsSchema, }); + + this.registerSubAction({ + name: SUB_ACTION.INVOKE_AI, + method: 'invokeAI', + schema: InvokeAIActionParamsSchema, + }); + + this.registerSubAction({ + name: SUB_ACTION.INVOKE_STREAM, + method: 'invokeStream', + schema: InvokeAIActionParamsSchema, + }); } protected getResponseErrorMessage(error: AxiosError<{ message?: string }>): string { @@ -185,4 +230,111 @@ export class GeminiConnector extends SubActionConnector { return { completion: completionText, usageMetadata }; } + + private async streamAPI({ + body, + model: reqModel, + signal, + timeout, + }: RunActionParams): Promise { + const currentModel = reqModel ?? this.model; + const path = `/v1/projects/${this.gcpProjectID}/locations/${this.gcpRegion}/publishers/google/models/${currentModel}:streamGenerateContent?alt=sse`; + const token = await this.getAccessToken(); + + const response = await this.request({ + url: `${this.url}${path}`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: body, + responseType: 'stream', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + signal, + timeout: timeout ?? DEFAULT_TIMEOUT_MS, + }); + + return response.data.pipe(new PassThrough()); + } + + public async invokeAI({ + messages, + model, + temperature = 0, + signal, + timeout, + }: InvokeAIActionParams): Promise { + const res = await this.runApi({ + body: JSON.stringify(formatGeminiPayload(messages, temperature)), + model, + signal, + timeout, + }); + + return { message: res.completion, usageMetadata: res.usageMetadata }; + } + + /** + * takes in an array of messages and a model as inputs. It calls the streamApi method to make a + * request to the Gemini API with the formatted messages and model. It then returns a Transform stream + * that pipes the response from the API through the transformToString function, + * which parses the proprietary response into a string of the response text alone + * @param messages An array of messages to be sent to the API + * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. + */ + public async invokeStream({ + messages, + model, + stopSequences, + temperature = 0, + signal, + timeout, + }: InvokeAIActionParams): Promise { + const res = (await this.streamAPI({ + body: JSON.stringify(formatGeminiPayload(messages, temperature)), + model, + stopSequences, + signal, + timeout, + })) as unknown as IncomingMessage; + return res; + } } + +/** Format the json body to meet Gemini payload requirements */ +const formatGeminiPayload = ( + data: Array<{ role: string; content: string }>, + temperature: number +): Payload => { + const payload: Payload = { + contents: [], + generation_config: { + temperature, + maxOutputTokens: DEFAULT_TOKEN_LIMIT, + }, + }; + let previousRole: string | null = null; + + for (const row of data) { + const correctRole = row.role === 'assistant' ? 'model' : 'user'; + if (correctRole === 'user' && previousRole === 'user') { + /** Append to the previous 'user' content + * This is to ensure that multiturn requests alternate between user and model + */ + payload.contents[payload.contents.length - 1].parts[0].text += ` ${row.content}`; + } else { + // Add a new entry + payload.contents.push({ + role: correctRole, + parts: [ + { + text: row.content, + }, + ], + }); + } + previousRole = correctRole; + } + return payload; +}; From dce29e277b27f19b13ce90c4a74cac66c9fc2c79 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 17 Jun 2024 19:57:47 +0200 Subject: [PATCH 024/127] [kbn-test] call Kibana API to fetch current user profile (#186279) Related to #185870 In this PR I move user_profile fetching out of SAML session creation to its `sessionManager.getUserData()`: - rely on Kibana Security API for both local/Kibana CI and MKI cases (currently it is cloud and cached on saml session creation) - do not cache profile data in test service, Kibana API is fast enough I deleted the tests that no longer relevant --- packages/kbn-test/src/auth/saml_auth.ts | 11 ++- packages/kbn-test/src/auth/session_manager.ts | 17 ++++- .../kbn-test/src/auth/sesson_manager.test.ts | 71 ++++++++++++++----- .../common/platform_security/index.ts | 1 - .../platform_security/request_as_viewer.ts | 36 ---------- .../page_objects/svl_common_page.ts | 6 +- .../common/platform_security/index.ts | 1 - .../user_profiles/user_profiles.ts | 2 +- .../platform_security/viewer_role_login.ts | 32 --------- .../shared/services/svl_user_manager.ts | 4 ++ 10 files changed, 81 insertions(+), 100 deletions(-) delete mode 100644 x-pack/test_serverless/api_integration/test_suites/common/platform_security/request_as_viewer.ts delete mode 100644 x-pack/test_serverless/functional/test_suites/common/platform_security/viewer_role_login.ts diff --git a/packages/kbn-test/src/auth/saml_auth.ts b/packages/kbn-test/src/auth/saml_auth.ts index a88d11c6a5bc9..99343c8c6912b 100644 --- a/packages/kbn-test/src/auth/saml_auth.ts +++ b/packages/kbn-test/src/auth/saml_auth.ts @@ -24,11 +24,9 @@ import { export class Session { readonly cookie; readonly email; - readonly fullname; - constructor(cookie: Cookie, email: string, fullname: string) { + constructor(cookie: Cookie, email: string) { this.cookie = cookie; this.email = email; - this.fullname = fullname; } getCookieValue() { @@ -239,7 +237,7 @@ export const finishSAMLHandshake = async ({ ); }; -const getSecurityProfile = async ({ +export const getSecurityProfile = async ({ kbnHost, cookie, log, @@ -274,8 +272,7 @@ export const createCloudSAMLSession = async (params: CloudSamlSessionParams) => const { location, sid } = await createSAMLRequest(kbnHost, kbnVersion, log); const samlResponse = await createSAMLResponse({ location, ecSession, email, kbnHost, log }); const cookie = await finishSAMLHandshake({ kbnHost, samlResponse, sid, log }); - const userProfile = await getSecurityProfile({ kbnHost, cookie, log }); - return new Session(cookie, email, userProfile.full_name); + return new Session(cookie, email); }; export const createLocalSAMLSession = async (params: LocalSamlSessionParams) => { @@ -288,5 +285,5 @@ export const createLocalSAMLSession = async (params: LocalSamlSessionParams) => roles: [role], }); const cookie = await finishSAMLHandshake({ kbnHost, samlResponse, log }); - return new Session(cookie, email, fullname); + return new Session(cookie, email); }; diff --git a/packages/kbn-test/src/auth/session_manager.ts b/packages/kbn-test/src/auth/session_manager.ts index a8edca981c1d4..1783c3f389aa1 100644 --- a/packages/kbn-test/src/auth/session_manager.ts +++ b/packages/kbn-test/src/auth/session_manager.ts @@ -13,7 +13,12 @@ import { resolve } from 'path'; import Url from 'url'; import { KbnClient } from '../kbn_client'; import { readCloudUsersFromFile } from './helper'; -import { createCloudSAMLSession, createLocalSAMLSession, Session } from './saml_auth'; +import { + createCloudSAMLSession, + createLocalSAMLSession, + getSecurityProfile, + Session, +} from './saml_auth'; import { Role, User } from './types'; export interface HostOptions { @@ -146,8 +151,14 @@ export class SamlSessionManager { return session.getCookieValue(); } + async getEmail(role: string) { + const session = await this.getSessionByRole(role); + return session.email; + } + async getUserData(role: string) { - const { email, fullname } = await this.getSessionByRole(role); - return { email, fullname }; + const { cookie } = await this.getSessionByRole(role); + const profileData = await getSecurityProfile({ kbnHost: this.kbnHost, cookie, log: this.log }); + return profileData; } } diff --git a/packages/kbn-test/src/auth/sesson_manager.test.ts b/packages/kbn-test/src/auth/sesson_manager.test.ts index f0679917654a0..df037ebdf04e4 100644 --- a/packages/kbn-test/src/auth/sesson_manager.test.ts +++ b/packages/kbn-test/src/auth/sesson_manager.test.ts @@ -12,7 +12,7 @@ import { Session } from './saml_auth'; import { SamlSessionManager } from './session_manager'; import * as samlAuth from './saml_auth'; import * as helper from './helper'; -import { Role, User } from './types'; +import { Role, User, UserProfile } from './types'; import { SERVERLESS_ROLES_ROOT_PATH } from '@kbn/es'; const log = new ToolingLog(); @@ -23,6 +23,7 @@ const roleEditor = 'editor'; const createLocalSAMLSessionMock = jest.spyOn(samlAuth, 'createLocalSAMLSession'); const createCloudSAMLSessionMock = jest.spyOn(samlAuth, 'createCloudSAMLSession'); +const getSecurityProfileMock = jest.spyOn(samlAuth, 'getSecurityProfile'); const readCloudUsersFromFileMock = jest.spyOn(helper, 'readCloudUsersFromFile'); const isValidHostnameMock = jest.spyOn(helper, 'isValidHostname'); @@ -42,7 +43,7 @@ describe('SamlSessionManager', () => { .KbnClient.mockImplementation(() => ({ version: { get } })); get.mockImplementation(() => Promise.resolve('8.12.0')); - createLocalSAMLSessionMock.mockResolvedValue(new Session(cookieInstance, email, fullname)); + createLocalSAMLSessionMock.mockResolvedValue(new Session(cookieInstance, testEmail)); }); const hostOptions = { @@ -59,8 +60,8 @@ describe('SamlSessionManager', () => { log, supportedRoles, }; - const email = 'testuser@elastic.com'; - const fullname = 'Test User'; + const testEmail = 'testuser@elastic.com'; + const testFullname = 'Test User'; const cookieInstance = Cookie.parse( 'sid=kbn_cookie_value; Path=/; Expires=Wed, 01 Oct 2023 07:00:00 GMT' )!; @@ -91,10 +92,26 @@ describe('SamlSessionManager', () => { expect(createCloudSAMLSessionMock.mock.calls).toHaveLength(0); }); - test(`'getUserData' should return the correct email & fullname`, async () => { + test(`'getEmail' return the correct email`, async () => { const samlSessionManager = new SamlSessionManager(samlSessionManagerOptions); - const data = await samlSessionManager.getUserData(roleViewer); - expect(data).toEqual({ email, fullname }); + const email = await samlSessionManager.getEmail(roleEditor); + expect(email).toBe(testEmail); + }); + + test(`'getUserData' should call security API and return user profile data`, async () => { + const testData: UserProfile = { + username: '6ta90xc', + roles: [roleEditor], + full_name: testFullname, + email: testEmail, + enabled: true, + elastic_cloud_user: false, + }; + getSecurityProfileMock.mockResolvedValueOnce(testData); + const samlSessionManager = new SamlSessionManager(samlSessionManagerOptions); + const userData = await samlSessionManager.getUserData(roleViewer); + + expect(userData).toEqual(testData); }); test(`throws error when role is not in 'supportedRoles'`, async () => { @@ -117,6 +134,15 @@ describe('SamlSessionManager', () => { test(`doesn't throw error when supportedRoles is not defined`, async () => { const nonExistingRole = 'tester'; + const testData: UserProfile = { + username: '6ta90xc', + roles: [nonExistingRole], + full_name: testFullname, + email: testEmail, + enabled: true, + elastic_cloud_user: false, + }; + getSecurityProfileMock.mockResolvedValueOnce(testData); const samlSessionManager = new SamlSessionManager({ hostOptions, log, @@ -127,6 +153,7 @@ describe('SamlSessionManager', () => { await samlSessionManager.getUserData(nonExistingRole); expect(createLocalSAMLSessionMock.mock.calls).toHaveLength(1); expect(createCloudSAMLSessionMock.mock.calls).toHaveLength(0); + expect(getSecurityProfileMock.mock.calls).toHaveLength(1); }); }); @@ -184,9 +211,7 @@ describe('SamlSessionManager', () => { .KbnClient.mockImplementation(() => ({ version: { get } })); get.mockImplementationOnce(() => Promise.resolve('8.12.0')); - createCloudSAMLSessionMock.mockResolvedValue( - new Session(cloudCookieInstance, cloudEmail, cloudFullname) - ); + createCloudSAMLSessionMock.mockResolvedValue(new Session(cloudCookieInstance, cloudEmail)); readCloudUsersFromFileMock.mockReturnValue(cloudUsers); }); @@ -201,9 +226,7 @@ describe('SamlSessionManager', () => { test(`'getSessionCookieForRole' should return the actual cookie value`, async () => { const samlSessionManager = new SamlSessionManager(samlSessionManagerOptions); - createCloudSAMLSessionMock.mockResolvedValue( - new Session(cloudCookieInstance, cloudEmail, cloudFullname) - ); + createCloudSAMLSessionMock.mockResolvedValue(new Session(cloudCookieInstance, cloudEmail)); const cookie = await samlSessionManager.getSessionCookieForRole(roleViewer); expect(cookie).toBe(cloudCookieInstance.value); }); @@ -223,10 +246,26 @@ describe('SamlSessionManager', () => { expect(createCloudSAMLSessionMock.mock.calls).toHaveLength(2); }); - test(`'getUserData' should return the correct email & fullname`, async () => { + test(`'getEmail' return the correct email`, async () => { const samlSessionManager = new SamlSessionManager(samlSessionManagerOptions); - const data = await samlSessionManager.getUserData(roleViewer); - expect(data).toEqual({ email: cloudEmail, fullname: cloudFullname }); + const email = await samlSessionManager.getEmail(roleViewer); + expect(email).toBe(cloudEmail); + }); + + test(`'getUserData' should call security API and return user profile data`, async () => { + const testData: UserProfile = { + username: '92qab123', + roles: [roleViewer], + full_name: cloudFullname, + email: cloudEmail, + enabled: true, + elastic_cloud_user: true, + }; + getSecurityProfileMock.mockResolvedValueOnce(testData); + const samlSessionManager = new SamlSessionManager(samlSessionManagerOptions); + const userData = await samlSessionManager.getUserData(roleViewer); + + expect(userData).toEqual(testData); }); test(`throws error for non-existing role when 'supportedRoles' is defined`, async () => { diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts index fab6e47e87969..e5f3f4a86a923 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts @@ -22,7 +22,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./role_mappings')); loadTestFile(require.resolve('./sessions')); loadTestFile(require.resolve('./users')); - loadTestFile(require.resolve('./request_as_viewer')); loadTestFile(require.resolve('./user_profiles')); loadTestFile(require.resolve('./views')); loadTestFile(require.resolve('./feature_check')); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/request_as_viewer.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/request_as_viewer.ts deleted file mode 100644 index 7931f28f55df7..0000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/request_as_viewer.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - describe('security/me as viewer', () => { - const svlUserManager = getService('svlUserManager'); - const svlCommonApi = getService('svlCommonApi'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let credentials: { Cookie: string }; - - before(async () => { - // get auth header for Viewer role - credentials = await svlUserManager.getApiCredentialsForRole('viewer'); - }); - - it('returns valid user data for authenticated request', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/me') - .set(svlCommonApi.getInternalRequestHeader()) - .set(credentials); - - const userData = await svlUserManager.getUserData('viewer'); - - expect(status).to.be(200); - expect(body.full_name).to.be(userData.fullname); - expect(body.email).to.be(userData.email); - }); - }); -} diff --git a/x-pack/test_serverless/functional/page_objects/svl_common_page.ts b/x-pack/test_serverless/functional/page_objects/svl_common_page.ts index 49113e5565435..827821c128daa 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_common_page.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_common_page.ts @@ -100,14 +100,14 @@ export function SvlCommonPageProvider({ getService, getPageObjects }: FtrProvide .set(svlCommonApi.getInternalRequestHeader()) .set({ Cookie: `sid=${browserCookies[0].value}` }); - const userData = await svlUserManager.getUserData(role); + const email = await svlUserManager.getEmail(role); // email returned from API call must match the email for the specified role - if (body.email === userData.email) { + if (body.email === email) { log.debug(`The new cookie is properly set for '${role}' role`); } else { log.debug(`API response body: ${JSON.stringify(body)}`); throw new Error( - `Cookie is not set properly, expected email is '${userData.email}', but found '${body.email}'` + `Cookie is not set properly, expected email is '${email}', but found '${body.email}'` ); } // Verifying that we are logged in diff --git a/x-pack/test_serverless/functional/test_suites/common/platform_security/index.ts b/x-pack/test_serverless/functional/test_suites/common/platform_security/index.ts index 7427384fc73bf..bbb66a9841868 100644 --- a/x-pack/test_serverless/functional/test_suites/common/platform_security/index.ts +++ b/x-pack/test_serverless/functional/test_suites/common/platform_security/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Serverless Common UI - Platform Security', function () { - loadTestFile(require.resolve('./viewer_role_login')); loadTestFile(require.resolve('./api_keys')); loadTestFile(require.resolve('./navigation/avatar_menu')); loadTestFile(require.resolve('./user_profiles/user_profiles')); diff --git a/x-pack/test_serverless/functional/test_suites/common/platform_security/user_profiles/user_profiles.ts b/x-pack/test_serverless/functional/test_suites/common/platform_security/user_profiles/user_profiles.ts index c9c61d5d3a6a9..50313bc4da7cf 100644 --- a/x-pack/test_serverless/functional/test_suites/common/platform_security/user_profiles/user_profiles.ts +++ b/x-pack/test_serverless/functional/test_suites/common/platform_security/user_profiles/user_profiles.ts @@ -33,7 +33,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const actualFullname = await pageObjects.userProfiles.getProfileFullname(); const actualEmail = await pageObjects.userProfiles.getProfileEmail(); - expect(actualFullname).to.be(userData.fullname); + expect(actualFullname).to.be(userData.full_name); expect(actualEmail).to.be(userData.email); }); diff --git a/x-pack/test_serverless/functional/test_suites/common/platform_security/viewer_role_login.ts b/x-pack/test_serverless/functional/test_suites/common/platform_security/viewer_role_login.ts deleted file mode 100644 index 767abe540c2f5..0000000000000 --- a/x-pack/test_serverless/functional/test_suites/common/platform_security/viewer_role_login.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -const VIEWER_ROLE = 'viewer'; - -export default function ({ getPageObject, getService }: FtrProviderContext) { - describe(`Login as ${VIEWER_ROLE}`, function () { - const svlCommonPage = getPageObject('svlCommonPage'); - const testSubjects = getService('testSubjects'); - const svlUserManager = getService('svlUserManager'); - - before(async () => { - await svlCommonPage.loginWithRole(VIEWER_ROLE); - }); - - it('should be able to see correct profile', async () => { - await svlCommonPage.assertProjectHeaderExists(); - await svlCommonPage.assertUserAvatarExists(); - await svlCommonPage.clickUserAvatar(); - await svlCommonPage.assertUserMenuExists(); - const actualFullname = await testSubjects.getVisibleText('contextMenuPanelTitle'); - const userData = await svlUserManager.getUserData(VIEWER_ROLE); - expect(actualFullname).to.be(userData.fullname); - }); - }); -} diff --git a/x-pack/test_serverless/shared/services/svl_user_manager.ts b/x-pack/test_serverless/shared/services/svl_user_manager.ts index 3568da0c6b87b..12fa18eee6673 100644 --- a/x-pack/test_serverless/shared/services/svl_user_manager.ts +++ b/x-pack/test_serverless/shared/services/svl_user_manager.ts @@ -78,6 +78,10 @@ export function SvlUserManagerProvider({ getService }: FtrProviderContext) { async getApiCredentialsForRole(role: string) { return sessionManager.getApiCredentialsForRole(role); }, + async getEmail(role: string) { + return sessionManager.getEmail(role); + }, + async getUserData(role: string) { return sessionManager.getUserData(role); }, From 51e84f49ba0069793e763048cfb4b4a692ed5fb1 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Mon, 17 Jun 2024 11:18:39 -0700 Subject: [PATCH 025/127] [DOCS] Standardize advanced setting deprecation admonitions (#186314) --- docs/management/advanced-options.asciidoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 5de4ea45c3204..bad18a706cbf2 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -268,7 +268,8 @@ the `xpack.banners.backgroundColor` configuration property. [horizontal] [[xpackdashboardmode-roles]]`xpackDashboardMode:roles`:: -**Deprecated. Use <> instead.** +deprecated:[7.7.0] +Deprecated; use <> instead. The roles that belong to <>. [float] @@ -545,7 +546,7 @@ because requests can be spread across all shard copies. However, results might be inconsistent because different shards might be in different refresh states. [[search-includefrozen]]`search:includeFrozen`:: -**This setting is deprecated and will not be supported as of 9.0.** +deprecated:[7.16.0] Includes {ref}/frozen-indices.html[frozen indices] in results. Searching through frozen indices might increase the search time. This setting is off by default. Users must opt-in to include frozen indices. @@ -622,11 +623,11 @@ of buckets to try to represent. [horizontal] [[visualization-colormapping]]`visualization:colorMapping`:: -**This setting is deprecated and will not be supported in a future version.** +deprecated:[7.11.0] Maps values to specific colors in charts using the *Compatibility* palette. [[visualization-uselegacytimeaxis]]`visualization:useLegacyTimeAxis`:: -**This setting is deprecated and will not be supported in a future version.** +deprecated:[8.10.0] Enables the legacy time axis for charts in Lens, Discover, Visualize and TSVB [[visualization-heatmap-maxbuckets]]`visualization:heatmap:maxBuckets`:: From c091dd89ff8f39b5a74682cfbe06b6c472a7130c Mon Sep 17 00:00:00 2001 From: Saarika Bhasi <55930906+saarikabhasi@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:12:13 -0400 Subject: [PATCH 026/127] [Index management] Make create Inference endpoint from flyout async task (#184615) Currently, when a new inference endpoint is created from inference flyout, the flyout stays open until the endpoint is created. This may take long time when Elasticsearch models - `.elser_model_2` and `.multilingual-e5-small` is to be downloaded, deployed and inference endpoint is to be created. In this PR, When a new inference endpoint is saved, inference flyout is closed and the new inference endpoint is created by a callback function in the component. **Screen Recording** https://github.com/elastic/kibana/assets/55930906/8eabba1a-108a-4bf2-813a-66ceb291467c **Testing instructions** **update Elasticsearch to latest (only to test save mappings)** Since ES changes for the semantic_text has been merged to main, this can be tested against running ES from source or from latest snapshot - Update local branch with latest Elasticsearch changes from main - Run the elasticsearch: ./gradlew :run -Drun.license_type=trial - Manual test in UI **Frontend** - enable` xpack.index_management.dev.enableSemanticText` to true in `config/kibana.dev.yml` - Add a new field with type - Semantic_text - Click on drop down menu below `Select an inference endpoint` - Click Add inference Endpoint - Type new inference endpoint name and click Save endpoint - Save endpoint button should close the flyout - A new success notification toasts is shown with text "1 model is being deployed on your ml_node." - Add new field - Click Save mappings - should show a modal with model deployment status - After new endpoint is created, refresh button should hide the modal and save mappings should update mappings --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/inference_flyout_wrapper.tsx | 2 +- .../ml/inference_integration_flyout/types.ts | 2 +- .../helpers/http_requests.ts | 4 + .../index_details_page.helpers.ts | 46 +++- .../index_details_page.test.tsx | 154 ++++++++--- .../select_inference_id.test.tsx | 15 +- .../reference_field_selects.tsx | 13 +- .../field_parameters/select_inference_id.tsx | 118 ++++----- .../fields/create_field/create_field.tsx | 35 ++- .../semantic_text/use_semantic_text.test.ts | 241 +++++++++++++----- .../semantic_text/use_semantic_text.ts | 172 ++++++------- .../constants/field_options.tsx | 1 + .../mappings_editor/types/document_fields.ts | 15 ++ .../trained_models_deployment_modal.tsx | 4 +- ...ils_page_mappings_model_management.test.ts | 4 - ..._details_page_mappings_model_management.ts | 30 ++- .../hooks/use_ml_model_status_toasts.ts | 36 +++ x-pack/plugins/index_management/tsconfig.json | 4 +- 18 files changed, 594 insertions(+), 302 deletions(-) rename x-pack/plugins/index_management/{public/application/components/mappings_editor/components/document_fields/field_parameters => __jest__/client_integration/index_details_page}/select_inference_id.test.tsx (80%) create mode 100644 x-pack/plugins/index_management/public/hooks/use_ml_model_status_toasts.ts diff --git a/x-pack/packages/ml/inference_integration_flyout/components/inference_flyout_wrapper.tsx b/x-pack/packages/ml/inference_integration_flyout/components/inference_flyout_wrapper.tsx index d5e17de1ef4c7..d66540feccff1 100644 --- a/x-pack/packages/ml/inference_integration_flyout/components/inference_flyout_wrapper.tsx +++ b/x-pack/packages/ml/inference_integration_flyout/components/inference_flyout_wrapper.tsx @@ -78,7 +78,7 @@ export interface SaveMappingOnClick { taskType: InferenceTaskType, modelConfig: ModelConfig ) => void; - isCreateInferenceApiLoading: boolean; + isCreateInferenceApiLoading?: boolean; } export interface DocumentationProps { elserv2documentationUrl?: string; diff --git a/x-pack/packages/ml/inference_integration_flyout/types.ts b/x-pack/packages/ml/inference_integration_flyout/types.ts index 849706b12a84f..900778e254686 100644 --- a/x-pack/packages/ml/inference_integration_flyout/types.ts +++ b/x-pack/packages/ml/inference_integration_flyout/types.ts @@ -54,7 +54,7 @@ export interface ElasticsearchService { export enum Service { cohere = 'cohere', elser = 'elser', - huggingFace = 'huggingFace', + huggingFace = 'hugging_face', openai = 'openai', elasticsearch = 'elasticsearch', } diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 235e5090a2695..8bd8672b8fbba 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -209,6 +209,9 @@ const registerHttpRequestMockHelpers = ( const setCreateIndexResponse = (response?: HttpResponse, error?: ResponseError) => mockResponse('PUT', `${INTERNAL_API_BASE_PATH}/indices/create`, response, error); + const setInferenceModels = (response?: HttpResponse, error?: ResponseError) => + mockResponse('GET', `${API_BASE_PATH}/inference/all`, response, error); + return { setLoadTemplatesResponse, setLoadIndicesResponse, @@ -238,6 +241,7 @@ const registerHttpRequestMockHelpers = ( setGetFieldsFromIndices, setGetPrivilegesResponse, setCreateEnrichPolicy, + setInferenceModels, }; }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts index 5a15772d5e16a..91dd4d26c2a5b 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts @@ -13,7 +13,7 @@ import { } from '@kbn/test-jest-helpers'; import { HttpSetup } from '@kbn/core/public'; import { act } from 'react-dom/test-utils'; - +import { keys } from '@elastic/eui'; import { IndexDetailsTabId } from '../../../common/constants'; import { IndexDetailsPage } from '../../../public/application/sections/home/index_list/details_page'; import { WithAppDependencies } from '../helpers'; @@ -56,6 +56,12 @@ export interface IndexDetailsPageTestBed extends TestBed { setSearchBarValue: (searchValue: string) => Promise; findSearchResult: () => string; isSemanticTextBannerVisible: () => boolean; + selectSemanticTextField: (name: string, type: string) => Promise; + isReferenceFieldVisible: () => void; + selectInferenceIdButtonExists: () => void; + openSelectInferencePopover: () => void; + expectDefaultInferenceModelToExists: () => void; + expectCustomInferenceModelToExists: (customInference: string) => Promise; }; settings: { getCodeBlockContent: () => string; @@ -228,7 +234,7 @@ export const setup = async ({ component.update(); }, selectFilterFieldType: async (fieldType: string) => { - expect(testBed.exists('indexDetailsMappingsSelectFilter-text')).toBe(true); + expect(testBed.exists(fieldType)).toBe(true); await act(async () => { find(fieldType).simulate('click'); }); @@ -287,6 +293,7 @@ export const setup = async ({ await act(async () => { expect(exists('createFieldForm.addButton')).toBe(true); + expect(find('createFieldForm.addButton').props().disabled).toBeFalsy(); find('createFieldForm.addButton').simulate('click'); }); @@ -294,6 +301,41 @@ export const setup = async ({ } } }, + selectSemanticTextField: async (name: string, type: string) => { + expect(exists('comboBoxSearchInput')).toBe(true); + + const { form } = testBed; + form.setInputValue('nameParameterInput', name); + form.setInputValue('comboBoxSearchInput', type); + await act(async () => { + find('comboBoxSearchInput').simulate('keydown', { key: keys.ENTER }); + }); + // select semantic_text field + await act(async () => { + expect(exists('fieldTypesOptions-semantic_text')).toBe(true); + find('fieldTypesOptions-semantic_text').simulate('click'); + expect(exists('fieldTypesOptions-semantic_text')).toBe(false); + }); + }, + isReferenceFieldVisible: async () => { + expect(exists('referenceField.select')).toBe(true); + }, + selectInferenceIdButtonExists: async () => { + expect(exists('selectInferenceId')).toBe(true); + expect(exists('inferenceIdButton')).toBe(true); + find('inferenceIdButton').simulate('click'); + }, + openSelectInferencePopover: async () => { + expect(exists('addInferenceEndpointButton')).toBe(true); + expect(exists('manageInferenceEndpointButton')).toBe(true); + }, + expectDefaultInferenceModelToExists: async () => { + expect(exists('default-inference_elser_model_2')).toBe(true); + expect(exists('default-inference_e5')).toBe(true); + }, + expectCustomInferenceModelToExists: async (customInference: string) => { + expect(exists(customInference)).toBe(true); + }, }; const settings = { diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx index 37e2799678e79..18f43807041ff 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx @@ -18,6 +18,7 @@ import { breadcrumbService, IndexManagementBreadcrumb, } from '../../../public/application/services/breadcrumbs'; +import { documentationService } from '../../../public/application/services/documentation'; import { humanizeTimeStamp } from '../../../public/application/sections/home/data_stream_list/humanize_time_stamp'; import { createDataStreamPayload } from '../home/data_streams_tab.helpers'; import { @@ -58,6 +59,7 @@ describe('', () => { let httpSetup: ReturnType['httpSetup']; let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; jest.spyOn(breadcrumbService, 'setBreadcrumbs'); + jest.spyOn(documentationService, 'setup'); beforeEach(async () => { const mockEnvironment = setupEnvironment(); @@ -571,14 +573,9 @@ describe('', () => { }, }; beforeEach(async () => { - httpRequestsMockHelpers.setUpdateIndexMappingsResponse(testIndexName, { - acknowledged: true, - }); - await act(async () => { testBed = await setup({ httpSetup }); }); - testBed.component.update(); await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Mappings); await testBed.actions.mappings.clickAddFieldButton(); @@ -634,43 +631,6 @@ describe('', () => { ); }); - it('can add a semantic_text field and can save mappings', async () => { - const mockIndexMappingResponseForSemanticText: any = { - ...testIndexMappings.mappings, - properties: { - ...testIndexMappings.mappings.properties, - sem: { - type: 'semantic_text', - inference_id: 'my-elser', - }, - }, - }; - httpRequestsMockHelpers.setLoadIndexMappingResponse(testIndexName, { - mappings: mockIndexMappingResponseForSemanticText, - }); - await testBed.actions.mappings.addNewMappingFieldNameAndType([ - { name: 'sem', type: 'semantic_text' }, - ]); - await testBed.actions.mappings.clickSaveMappingsButton(); - // add field button is available again - expect(testBed.exists('indexDetailsMappingsAddField')).toBe(true); - expect(testBed.find('semField-datatype').props()['data-type-value']).toBe('semantic_text'); - expect(httpSetup.get).toHaveBeenCalledTimes(5); - expect(httpSetup.get).toHaveBeenLastCalledWith( - `${API_BASE_PATH}/mapping/${testIndexName}`, - requestOptions - ); - // refresh mappings and page re-renders - expect(testBed.exists('indexDetailsMappingsAddField')).toBe(true); - expect(testBed.actions.mappings.isSearchBarDisabled()).toBe(false); - const treeViewContent = testBed.actions.mappings.getTreeViewContent('semField'); - expect(treeViewContent).toContain('sem'); - await testBed.actions.mappings.clickToggleViewButton(); - const jsonContent = testBed.actions.mappings.getCodeBlockContent(); - expect(jsonContent).toEqual( - JSON.stringify({ mappings: mockIndexMappingResponseForSemanticText }, null, 2) - ); - }); it('there is a callout with error message when save mappings fail', async () => { const error = { statusCode: 400, @@ -685,6 +645,116 @@ describe('', () => { await testBed.actions.mappings.clickSaveMappingsButton(); expect(testBed.actions.mappings.isSaveMappingsErrorDisplayed()).toBe(true); }); + describe('Add Semantic text field', () => { + const customInferenceModel = 'my-elser-model'; + beforeEach(async () => { + httpRequestsMockHelpers.setInferenceModels({ + data: [ + { + model_id: customInferenceModel, + task_type: 'sparse_embedding', + service: 'elser', + service_settings: { + num_allocations: 1, + num_threads: 1, + model_id: '.elser_model_2', + }, + task_settings: {}, + }, + ], + }); + await act(async () => { + testBed = await setup({ + httpSetup, + dependencies: { + config: { enableSemanticText: true }, + docLinks: { + links: { + ml: '', + enterpriseSearch: '', + }, + }, + plugins: { + ml: { + mlApi: { + trainedModels: { + getTrainedModels: jest.fn().mockResolvedValue([ + { + model_id: '.elser_model_2', + model_type: 'pytorch', + model_package: { + packaged_model_id: customInferenceModel, + model_repository: 'https://ml-models.elastic.co', + minimum_version: '11.0.0', + size: 438123914, + sha256: '', + metadata: {}, + tags: [], + vocabulary_file: 'elser_model_2.vocab.json', + }, + description: 'Elastic Learned Sparse EncodeR v2', + tags: ['elastic'], + }, + ]), + getTrainedModelStats: jest.fn().mockResolvedValue({ + count: 1, + trained_model_stats: [ + { + model_id: '.elser_model_2', + + deployment_stats: { + deployment_id: customInferenceModel, + model_id: '.elser_model_2', + threads_per_allocation: 1, + number_of_allocations: 1, + queue_capacity: 1024, + state: 'started', + }, + }, + { + model_id: '.elser_model_2', + + deployment_stats: { + deployment_id: '.elser_model_2', + model_id: '.elser_model_2', + threads_per_allocation: 1, + number_of_allocations: 1, + queue_capacity: 1024, + state: 'started', + }, + }, + ], + }), + }, + }, + }, + }, + }, + }); + }); + testBed.component.update(); + await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Mappings); + await testBed.actions.mappings.clickAddFieldButton(); + }); + it('can select semantic_text field', async () => { + await testBed.actions.mappings.selectSemanticTextField( + 'semantic_text_name', + 'Semantic text' + ); + + testBed.actions.mappings.isReferenceFieldVisible(); + testBed.actions.mappings.selectInferenceIdButtonExists(); + testBed.actions.mappings.openSelectInferencePopover(); + testBed.actions.mappings.expectDefaultInferenceModelToExists(); + testBed.actions.mappings.expectCustomInferenceModelToExists( + `custom-inference_${customInferenceModel}` + ); + + // can cancel new field + expect(testBed.exists('cancelButton')).toBe(true); + testBed.find('cancelButton').simulate('click'); + }); + }); }); describe('error loading mappings', () => { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx similarity index 80% rename from x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.test.tsx rename to x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx index 4222cf493a9bf..c734943ec4592 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx @@ -7,13 +7,13 @@ import { registerTestBed } from '@kbn/test-jest-helpers'; import { act } from 'react-dom/test-utils'; -import { SelectInferenceId } from './select_inference_id'; +import { SelectInferenceId } from '../../../public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id'; const onChangeMock = jest.fn(); const setValueMock = jest.fn(); const setNewInferenceEndpointMock = jest.fn(); -jest.mock('../../../../../app_context', () => ({ +jest.mock('../../../public/application/app_context', () => ({ useAppContext: jest.fn().mockReturnValue({ core: { application: {} }, docLinks: {}, @@ -30,6 +30,17 @@ jest.mock('../../../../../app_context', () => ({ }), })); +jest.mock( + '../../../public/application/components/component_templates/component_templates_context', + () => ({ + useComponentTemplatesContext: jest.fn().mockReturnValue({ + toasts: { + addError: jest.fn(), + addSuccess: jest.fn(), + }, + }), + }) +); describe('SelectInferenceId', () => { let exists: any; let find: any; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx index e8b939ab81f5d..b8f5e866b68a9 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx @@ -32,7 +32,11 @@ export const ReferenceFieldSelects = ({ Object.keys(data.mappings.properties).forEach((key) => { const field = data.mappings.properties[key]; if (field.type === 'text') { - referenceFieldOptions.push({ value: key, inputDisplay: key }); + referenceFieldOptions.push({ + value: key, + inputDisplay: key, + 'data-test-subj': `select-reference-field-${key}`, + }); } }); } @@ -47,14 +51,15 @@ export const ReferenceFieldSelects = ({ return subscription.unsubscribe; }, [subscribe, onChange]); - return ( -
+
{(field) => ( )} diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx index 1d09c2469c164..24b99ef9e7c08 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx @@ -35,28 +35,40 @@ import { ModelConfig, Service, } from '@kbn/inference_integration_flyout/types'; -import { FormattedMessage } from '@kbn/i18n-react'; import { InferenceFlyoutWrapper } from '@kbn/inference_integration_flyout/components/inference_flyout_wrapper'; import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; -import { extractErrorProperties } from '@kbn/ml-error-utils'; import { getFieldConfig } from '../../../lib'; import { useAppContext } from '../../../../../app_context'; import { Form, UseField, useForm } from '../../../shared_imports'; import { useLoadInferenceModels } from '../../../../../services/api'; import { getTrainedModelStats } from '../../../../../../hooks/use_details_page_mappings_model_management'; import { InferenceToModelIdMap } from '../fields'; +import { useMLModelNotificationToasts } from '../../../../../../hooks/use_ml_model_status_toasts'; +import { + CustomInferenceEndpointConfig, + DefaultInferenceModels, + DeploymentState, +} from '../../../types'; const inferenceServiceTypeElasticsearchModelMap: Record = { elser: ElasticsearchModelDefaultOptions.elser, elasticsearch: ElasticsearchModelDefaultOptions.e5, }; - +const uncheckSelectedModelOption = (options: EuiSelectableOption[]) => { + const checkedOption = options.find(({ checked }) => checked === 'on'); + if (checkedOption) { + checkedOption.checked = undefined; + } +}; interface Props { onChange(value: string): void; 'data-test-subj'?: string; setValue: (value: string) => void; - setNewInferenceEndpoint: (newInferenceEndpoint: InferenceToModelIdMap) => void; + setNewInferenceEndpoint: ( + newInferenceEndpoint: InferenceToModelIdMap, + customInferenceEndpointConfig: CustomInferenceEndpointConfig + ) => void; } export const SelectInferenceId = ({ onChange, @@ -76,16 +88,14 @@ export const SelectInferenceId = ({ }); }, [ml]); - const { form } = useForm({ defaultValue: { main: 'elser_model_2' } }); + const { form } = useForm({ defaultValue: { main: DefaultInferenceModels.elser_model_2 } }); const { subscribe } = form; const [isInferenceFlyoutVisible, setIsInferenceFlyoutVisible] = useState(false); - const [inferenceAddError, setInferenceAddError] = useState(undefined); const [availableTrainedModels, setAvailableTrainedModels] = useState< TrainedModelConfigResponse[] >([]); const onFlyoutClose = useCallback(() => { - setInferenceAddError(undefined); setIsInferenceFlyoutVisible(!isInferenceFlyoutVisible); }, [isInferenceFlyoutVisible]); useEffect(() => { @@ -111,16 +121,27 @@ export const SelectInferenceId = ({ const fieldConfigModelId = getFieldConfig('inference_id'); const defaultInferenceIds: EuiSelectableOption[] = useMemo(() => { - return [{ checked: 'on', label: 'elser_model_2' }, { label: 'e5' }]; + return [ + { + checked: 'on', + label: 'elser_model_2', + 'data-test-subj': 'default-inference_elser_model_2', + }, + { + label: 'e5', + 'data-test-subj': 'default-inference_e5', + }, + ]; }, []); - const { isLoading, data: models, resendRequest } = useLoadInferenceModels(); + const { isLoading, data: models } = useLoadInferenceModels(); const [options, setOptions] = useState([...defaultInferenceIds]); const inferenceIdOptionsFromModels = useMemo(() => { const inferenceIdOptions = models?.map((model: InferenceAPIConfigResponse) => ({ label: model.model_id, + 'data-test-subj': `custom-inference_${model.model_id}`, })) || []; return inferenceIdOptions; @@ -136,40 +157,48 @@ export const SelectInferenceId = ({ }; setOptions(Object.values(mergedOptions)); }, [inferenceIdOptionsFromModels, defaultInferenceIds]); - const [isCreateInferenceApiLoading, setIsCreateInferenceApiLoading] = useState(false); + + const { showErrorToasts } = useMLModelNotificationToasts(); const onSaveInferenceCallback = useCallback( async (inferenceId: string, taskType: InferenceTaskType, modelConfig: ModelConfig) => { - setIsCreateInferenceApiLoading(true); + setIsInferenceFlyoutVisible(!isInferenceFlyoutVisible); try { - await ml?.mlApi?.inferenceModels?.createInferenceEndpoint( - inferenceId, - taskType, - modelConfig - ); - setIsInferenceFlyoutVisible(!isInferenceFlyoutVisible); - setIsCreateInferenceApiLoading(false); - setInferenceAddError(undefined); + const isDeployable = + modelConfig.service === Service.elser || modelConfig.service === Service.elasticsearch; + + const newOption: EuiSelectableOption[] = [ + { + label: inferenceId, + checked: 'on', + 'data-test-subj': `custom-inference_${inferenceId}`, + }, + ]; + // uncheck selected endpoint id + uncheckSelectedModelOption(options); + + setOptions([...options, ...newOption]); + const trainedModelStats = await ml?.mlApi?.trainedModels.getTrainedModelStats(); const defaultEndpointId = inferenceServiceTypeElasticsearchModelMap[modelConfig.service] || ''; const newModelId: InferenceToModelIdMap = {}; newModelId[inferenceId] = { trainedModelId: defaultEndpointId, - isDeployable: - modelConfig.service === Service.elser || modelConfig.service === Service.elasticsearch, - isDeployed: getTrainedModelStats(trainedModelStats)[defaultEndpointId] === 'deployed', - defaultInferenceEndpoint: false, + isDeployable, + isDeployed: + getTrainedModelStats(trainedModelStats)[defaultEndpointId] === DeploymentState.DEPLOYED, + }; + const customInferenceEndpointConfig: CustomInferenceEndpointConfig = { + taskType, + modelConfig, }; - resendRequest(); - setNewInferenceEndpoint(newModelId); + setNewInferenceEndpoint(newModelId, customInferenceEndpointConfig); } catch (error) { - const errorObj = extractErrorProperties(error); - setInferenceAddError(errorObj.message); - setIsCreateInferenceApiLoading(false); + showErrorToasts(error); } }, - [isInferenceFlyoutVisible, resendRequest, ml, setNewInferenceEndpoint] + [isInferenceFlyoutVisible, ml, setNewInferenceEndpoint, options, showErrorToasts] ); useEffect(() => { const subscription = subscribe((updateData) => { @@ -182,7 +211,7 @@ export const SelectInferenceId = ({ }, [subscribe, onChange]); const selectedOptionLabel = options.find((option) => option.checked)?.label; useEffect(() => { - setValue(selectedOptionLabel ?? 'elser_model_2'); + setValue(selectedOptionLabel ?? DefaultInferenceModels.elser_model_2); }, [selectedOptionLabel, setValue]); const [isInferencePopoverVisible, setIsInferencePopoverVisible] = useState(false); const [inferenceEndpointError, setInferenceEndpointError] = useState( @@ -304,7 +333,7 @@ export const SelectInferenceId = ({ data-test-subj={dataTestSubj} searchable isLoading={isLoading} - singleSelection + singleSelection="always" searchProps={{ compressed: true, placeholder: i18n.translate( @@ -340,32 +369,6 @@ export const SelectInferenceId = ({ - - - - - - - - ) - } onInferenceEndpointChange={onInferenceEndpointChange} inferenceEndpointError={inferenceEndpointError} trainedModels={trainedModels} @@ -374,7 +377,6 @@ export const SelectInferenceId = ({ isInferenceFlyoutVisible={isInferenceFlyoutVisible} supportedNlpModels={docLinks.links.enterpriseSearch.supportedNlpModels} nlpImportModel={docLinks.links.ml.nlpImportModel} - isCreateInferenceApiLoading={isCreateInferenceApiLoading} setInferenceEndpointError={setInferenceEndpointError} /> )} diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx index f91be7bf55fe2..4a3f600753dd4 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx @@ -14,14 +14,20 @@ import { EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { ElasticsearchModelDefaultOptions } from '@kbn/inference_integration_flyout/types'; import { MlPluginStart } from '@kbn/ml-plugin/public'; import classNames from 'classnames'; -import React, { useCallback, useEffect } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { EUI_SIZE, TYPE_DEFINITION } from '../../../../constants'; import { fieldSerializer } from '../../../../lib'; import { useDispatch, useMappingsState } from '../../../../mappings_state_context'; import { Form, FormDataProvider, UseField, useForm, useFormData } from '../../../../shared_imports'; -import { Field, MainType, NormalizedFields } from '../../../../types'; +import { + CustomInferenceEndpointConfig, + Field, + MainType, + NormalizedFields, +} from '../../../../types'; import { NameParameter, SubTypeParameter, TypeParameter } from '../../field_parameters'; import { ReferenceFieldSelects } from '../../field_parameters/reference_field_selects'; import { SelectInferenceId } from '../../field_parameters/select_inference_id'; @@ -32,10 +38,9 @@ import { useSemanticText } from './semantic_text/use_semantic_text'; const formWrapper = (props: any) =>
; export interface InferenceToModelIdMap { [key: string]: { - trainedModelId?: string; + trainedModelId: ElasticsearchModelDefaultOptions | string; isDeployed: boolean; isDeployable: boolean; - defaultInferenceEndpoint: boolean; }; } @@ -88,7 +93,9 @@ export const CreateField = React.memo(function CreateFieldComponent({ return subscription.unsubscribe; }, [dispatch, subscribe]); - + const [customInferenceEndpointConfig, setCustomInferenceEndpointConfig] = useState< + CustomInferenceEndpointConfig | undefined + >(undefined); const cancel = () => { if (isAddingFields && onCancelAddingNewFields) { onCancelAddingNewFields(); @@ -125,7 +132,7 @@ export const CreateField = React.memo(function CreateFieldComponent({ form.reset(); if (data.type === 'semantic_text' && !clickOutside) { - handleSemanticText(data); + handleSemanticText(data, customInferenceEndpointConfig); } else { dispatch({ type: 'field.add', value: data }); } @@ -283,7 +290,10 @@ export const CreateField = React.memo(function CreateFieldComponent({ }} {/* Field inference_id for semantic_text field type */} - + {renderFormActions()} @@ -311,16 +321,20 @@ function ReferenceFieldCombo({ indexName }: { indexName?: string }) { interface InferenceProps { setValue: (value: string) => void; + setCustomInferenceEndpointConfig: (config: CustomInferenceEndpointConfig) => void; } -function InferenceIdCombo({ setValue }: InferenceProps) { +function InferenceIdCombo({ setValue, setCustomInferenceEndpointConfig }: InferenceProps) { const { inferenceToModelIdMap } = useMappingsState(); const dispatch = useDispatch(); const [{ type }] = useFormData({ watch: 'type' }); // update new inferenceEndpoint const setNewInferenceEndpoint = useCallback( - (newInferenceEndpoint: InferenceToModelIdMap) => { + ( + newInferenceEndpoint: InferenceToModelIdMap, + customInferenceEndpointConfig: CustomInferenceEndpointConfig + ) => { dispatch({ type: 'inferenceToModelIdMap.update', value: { @@ -330,8 +344,9 @@ function InferenceIdCombo({ setValue }: InferenceProps) { }, }, }); + setCustomInferenceEndpointConfig(customInferenceEndpointConfig); }, - [dispatch, inferenceToModelIdMap] + [dispatch, inferenceToModelIdMap, setCustomInferenceEndpointConfig] ); if (type === undefined || type[0]?.value !== 'semantic_text') { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.test.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.test.ts index 062c0b93c303e..4833562e58e31 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.test.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.test.ts @@ -6,7 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { Field } from '../../../../../types'; +import { CustomInferenceEndpointConfig, Field } from '../../../../../types'; import { useSemanticText } from './use_semantic_text'; import { act } from 'react-dom/test-utils'; @@ -15,22 +15,54 @@ const mlMock: any = { inferenceModels: { createInferenceEndpoint: jest.fn().mockResolvedValue({}), }, - trainedModels: { - startModelAllocation: jest.fn().mockResolvedValue({}), - getTrainedModels: jest.fn().mockResolvedValue([ - { - fully_defined: true, - }, - ]), - }, }, }; -const mockFieldData = { - name: 'name', - type: 'semantic_text', - inferenceId: 'elser_model_2', -} as Field; +const mockField: Record = { + elser_model_2: { + name: 'name', + type: 'semantic_text', + inferenceId: 'elser_model_2', + }, + e5: { + name: 'name', + type: 'semantic_text', + inferenceId: 'e5', + }, + openai: { + name: 'name', + type: 'semantic_text', + inferenceId: 'openai', + }, + my_elser_endpoint: { + name: 'name', + type: 'semantic_text', + inferenceId: 'my_elser_endpoint', + }, +}; + +const mockConfig: Record = { + openai: { + taskType: 'text_embedding', + modelConfig: { + service: 'openai', + service_settings: { + api_key: 'test', + model_id: 'text-embedding-ada-002', + }, + }, + }, + elser: { + taskType: 'sparse_embedding', + modelConfig: { + service: 'elser', + service_settings: { + num_allocations: 1, + num_threads: 1, + }, + }, + }, +}; const mockDispatch = jest.fn(); @@ -38,13 +70,21 @@ jest.mock('../../../../../mappings_state_context', () => ({ useMappingsState: jest.fn().mockReturnValue({ inferenceToModelIdMap: { e5: { - defaultInferenceEndpoint: false, isDeployed: false, isDeployable: true, trainedModelId: '.multilingual-e5-small', }, elser_model_2: { - defaultInferenceEndpoint: true, + isDeployed: false, + isDeployable: true, + trainedModelId: '.elser_model_2', + }, + openai: { + isDeployed: false, + isDeployable: false, + trainedModelId: '', + }, + my_elser_endpoint: { isDeployed: false, isDeployable: true, trainedModelId: '.elser_model_2', @@ -63,24 +103,108 @@ jest.mock('../../../../../../component_templates/component_templates_context', ( }), })); +jest.mock('../../../../../../../services/api', () => ({ + getInferenceModels: jest.fn().mockResolvedValue({ + data: [ + { + model_id: 'e5', + task_type: 'text_embedding', + service: 'elasticsearch', + service_settings: { + num_allocations: 1, + num_threads: 1, + model_id: '.multilingual-e5-small', + }, + task_settings: {}, + }, + ], + }), +})); + describe('useSemanticText', () => { - let form: any; + let mockForm: any; beforeEach(() => { jest.clearAllMocks(); - form = { - getFields: jest.fn().mockReturnValue({ - referenceField: { value: 'title' }, - name: { value: 'sem' }, - type: { value: [{ value: 'semantic_text' }] }, - inferenceId: { value: 'e5' }, - }), + mockForm = { + form: { + getFields: jest.fn().mockReturnValue({ + referenceField: { value: 'title' }, + name: { value: 'sem' }, + type: { value: [{ value: 'semantic_text' }] }, + inferenceId: { value: 'e5' }, + }), + }, + thirdPartyModel: { + getFields: jest.fn().mockReturnValue({ + referenceField: { value: 'title' }, + name: { value: 'semantic_text_openai_endpoint' }, + type: { value: [{ value: 'semantic_text' }] }, + inferenceId: { value: 'openai' }, + }), + }, + elasticModelEndpointCreatedfromFlyout: { + getFields: jest.fn().mockReturnValue({ + referenceField: { value: 'title' }, + name: { value: 'semantic_text_elserServiceType_endpoint' }, + type: { value: [{ value: 'semantic_text' }] }, + inferenceId: { value: 'my_elser_endpoint' }, + }), + }, }; }); + it('should handle semantic text with third party model correctly', async () => { + const { result } = renderHook(() => + useSemanticText({ + form: mockForm.thirdPartyModel, + setErrorsInTrainedModelDeployment: jest.fn(), + ml: mlMock, + }) + ); + await act(async () => { + result.current.setInferenceValue('openai'); + result.current.handleSemanticText(mockField.openai, mockConfig.openai); + }); + expect(mockDispatch).toHaveBeenCalledWith({ + type: 'field.addSemanticText', + value: mockField.openai, + }); + expect(mlMock.mlApi.inferenceModels.createInferenceEndpoint).toHaveBeenCalledWith( + 'openai', + 'text_embedding', + mockConfig.openai.modelConfig + ); + }); + it('should handle semantic text with inference endpoint created from flyout correctly', async () => { + const { result } = renderHook(() => + useSemanticText({ + form: mockForm.elasticModelEndpointCreatedfromFlyout, + setErrorsInTrainedModelDeployment: jest.fn(), + ml: mlMock, + }) + ); + await act(async () => { + result.current.setInferenceValue('my_elser_endpoint'); + result.current.handleSemanticText(mockField.my_elser_endpoint, mockConfig.elser); + }); + expect(mockDispatch).toHaveBeenCalledWith({ + type: 'field.addSemanticText', + value: mockField.my_elser_endpoint, + }); + expect(mlMock.mlApi.inferenceModels.createInferenceEndpoint).toHaveBeenCalledWith( + 'my_elser_endpoint', + 'sparse_embedding', + mockConfig.elser.modelConfig + ); + }); it('should populate the values from the form', () => { const { result } = renderHook(() => - useSemanticText({ form, setErrorsInTrainedModelDeployment: jest.fn(), ml: mlMock }) + useSemanticText({ + form: mockForm.form, + setErrorsInTrainedModelDeployment: jest.fn(), + ml: mlMock, + }) ); expect(result.current.referenceFieldComboValue).toBe('title'); @@ -91,23 +215,26 @@ describe('useSemanticText', () => { it('should handle semantic text correctly', async () => { const { result } = renderHook(() => - useSemanticText({ form, setErrorsInTrainedModelDeployment: jest.fn(), ml: mlMock }) + useSemanticText({ + form: mockForm.form, + setErrorsInTrainedModelDeployment: jest.fn(), + ml: mlMock, + }) ); await act(async () => { - result.current.handleSemanticText(mockFieldData); + result.current.handleSemanticText(mockField.elser_model_2); }); - expect(mlMock.mlApi.trainedModels.startModelAllocation).toHaveBeenCalledWith('.elser_model_2'); expect(mockDispatch).toHaveBeenCalledWith({ type: 'field.addSemanticText', - value: mockFieldData, + value: mockField.elser_model_2, }); expect(mlMock.mlApi.inferenceModels.createInferenceEndpoint).toHaveBeenCalledWith( 'elser_model_2', - 'text_embedding', + 'sparse_embedding', { - service: 'elasticsearch', + service: 'elser', service_settings: { num_allocations: 1, num_threads: 1, @@ -116,68 +243,42 @@ describe('useSemanticText', () => { } ); }); - - it('should invoke the download api if the model does not exist', async () => { - const mlMockWithModelNotDownloaded: any = { - mlApi: { - inferenceModels: { - createInferenceEndpoint: jest.fn(), - }, - trainedModels: { - startModelAllocation: jest.fn(), - getTrainedModels: jest.fn().mockResolvedValue([ - { - fully_defined: false, - }, - ]), - installElasticTrainedModelConfig: jest.fn().mockResolvedValue({}), - }, - }, - }; + it('does not call create inference endpoint api, if default endpoint already exists', async () => { const { result } = renderHook(() => useSemanticText({ - form, + form: mockForm.form, setErrorsInTrainedModelDeployment: jest.fn(), - ml: mlMockWithModelNotDownloaded, + ml: mlMock, }) ); await act(async () => { - result.current.handleSemanticText(mockFieldData); + result.current.setInferenceValue('e5'); + result.current.handleSemanticText(mockField.e5); }); - expect( - mlMockWithModelNotDownloaded.mlApi.trainedModels.installElasticTrainedModelConfig - ).toHaveBeenCalledWith('.elser_model_2'); - expect( - mlMockWithModelNotDownloaded.mlApi.trainedModels.startModelAllocation - ).toHaveBeenCalledWith('.elser_model_2'); - expect( - mlMockWithModelNotDownloaded.mlApi.inferenceModels.createInferenceEndpoint - ).toHaveBeenCalledWith('elser_model_2', 'text_embedding', { - service: 'elasticsearch', - service_settings: { - num_allocations: 1, - num_threads: 1, - model_id: '.elser_model_2', - }, + expect(mockDispatch).toHaveBeenCalledWith({ + type: 'field.addSemanticText', + value: mockField.e5, }); + + expect(mlMock.mlApi.inferenceModels.createInferenceEndpoint).not.toBeCalled(); }); it('handles errors correctly', async () => { const mockError = new Error('Test error'); - mlMock.mlApi?.trainedModels.startModelAllocation.mockImplementationOnce(() => { + mlMock.mlApi?.inferenceModels.createInferenceEndpoint.mockImplementationOnce(() => { throw mockError; }); const setErrorsInTrainedModelDeployment = jest.fn(); const { result } = renderHook(() => - useSemanticText({ form, setErrorsInTrainedModelDeployment, ml: mlMock }) + useSemanticText({ form: mockForm.form, setErrorsInTrainedModelDeployment, ml: mlMock }) ); await act(async () => { - result.current.handleSemanticText(mockFieldData); + result.current.handleSemanticText(mockField.elser_model_2); }); expect(setErrorsInTrainedModelDeployment).toHaveBeenCalledWith(expect.any(Function)); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts index dda1bfe794c97..01a37275a54dd 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts @@ -7,30 +7,39 @@ import { i18n } from '@kbn/i18n'; import { useCallback } from 'react'; -import { MlPluginStart, TrainedModelConfigResponse } from '@kbn/ml-plugin/public'; +import { MlPluginStart } from '@kbn/ml-plugin/public'; import React, { useEffect, useState } from 'react'; -import { useComponentTemplatesContext } from '../../../../../../component_templates/component_templates_context'; +import { ElasticsearchModelDefaultOptions } from '@kbn/inference_integration_flyout/types'; +import { InferenceTaskType } from '@elastic/elasticsearch/lib/api/types'; +import { InferenceAPIConfigResponse } from '@kbn/ml-trained-models-utils'; import { useDispatch, useMappingsState } from '../../../../../mappings_state_context'; import { FormHook } from '../../../../../shared_imports'; -import { Field } from '../../../../../types'; +import { CustomInferenceEndpointConfig, DefaultInferenceModels, Field } from '../../../../../types'; +import { useMLModelNotificationToasts } from '../../../../../../../../hooks/use_ml_model_status_toasts'; +import { getInferenceModels } from '../../../../../../../services/api'; interface UseSemanticTextProps { form: FormHook; ml?: MlPluginStart; setErrorsInTrainedModelDeployment: React.Dispatch> | undefined; } +interface DefaultInferenceEndpointConfig { + taskType: InferenceTaskType; + service: string; +} export function useSemanticText(props: UseSemanticTextProps) { const { form, setErrorsInTrainedModelDeployment, ml } = props; const { inferenceToModelIdMap } = useMappingsState(); - const { toasts } = useComponentTemplatesContext(); const dispatch = useDispatch(); - const [referenceFieldComboValue, setReferenceFieldComboValue] = useState(); const [nameValue, setNameValue] = useState(); const [inferenceIdComboValue, setInferenceIdComboValue] = useState(); const [semanticFieldType, setSemanticTextFieldType] = useState(); - const [inferenceValue, setInferenceValue] = useState('elser_model_2'); + const [inferenceValue, setInferenceValue] = useState( + DefaultInferenceModels.elser_model_2 + ); + const { showSuccessToasts, showErrorToasts } = useMLModelNotificationToasts(); const useFieldEffect = ( semanticTextform: FormHook, @@ -65,113 +74,92 @@ export function useSemanticText(props: UseSemanticTextProps) { } }, [form, inferenceId, inferenceToModelIdMap]); - const isModelDownloaded = useCallback( - async (modelId: string) => { + const createInferenceEndpoint = useCallback( + async ( + trainedModelId: ElasticsearchModelDefaultOptions | string, + data: Field, + customInferenceEndpointConfig?: CustomInferenceEndpointConfig + ) => { + if (data.inferenceId === undefined) { + throw new Error( + i18n.translate('xpack.idxMgmt.mappingsEditor.createField.undefinedInferenceIdError', { + defaultMessage: 'InferenceId is undefined while creating the inference endpoint.', + }) + ); + } + const defaultInferenceEndpointConfig: DefaultInferenceEndpointConfig = { + service: + trainedModelId === ElasticsearchModelDefaultOptions.elser ? 'elser' : 'elasticsearch', + taskType: + trainedModelId === ElasticsearchModelDefaultOptions.elser + ? 'sparse_embedding' + : 'text_embedding', + }; + + const modelConfig = customInferenceEndpointConfig + ? customInferenceEndpointConfig.modelConfig + : { + service: defaultInferenceEndpointConfig.service, + service_settings: { + num_allocations: 1, + num_threads: 1, + model_id: trainedModelId, + }, + }; + const taskType: InferenceTaskType = + customInferenceEndpointConfig?.taskType ?? defaultInferenceEndpointConfig.taskType; try { - const response: TrainedModelConfigResponse[] | undefined = - await ml?.mlApi?.trainedModels.getTrainedModels(modelId, { - include: 'definition_status', - }); - return !!response?.[0]?.fully_defined; + await ml?.mlApi?.inferenceModels?.createInferenceEndpoint( + data.inferenceId, + taskType, + modelConfig + ); } catch (error) { - if (error.body.statusCode !== 404) { - throw error; - } + throw error; } - return false; }, - [ml?.mlApi?.trainedModels] + [ml?.mlApi?.inferenceModels] ); - const createInferenceEndpoint = ( - trainedModelId: string, - defaultInferenceEndpoint: boolean, - data: Field + const handleSemanticText = async ( + data: Field, + customInferenceEndpointConfig?: CustomInferenceEndpointConfig ) => { - if (data.inferenceId === undefined) { - throw new Error( - i18n.translate('xpack.idxMgmt.mappingsEditor.createField.undefinedInferenceIdError', { - defaultMessage: 'InferenceId is undefined while creating the inference endpoint.', - }) - ); - } - - if (trainedModelId && defaultInferenceEndpoint) { - const modelConfig = { - service: 'elasticsearch', - service_settings: { - num_allocations: 1, - num_threads: 1, - model_id: trainedModelId, - }, - }; - - ml?.mlApi?.inferenceModels?.createInferenceEndpoint( - data.inferenceId, - 'text_embedding', - modelConfig - ); - } - }; - - const handleSemanticText = async (data: Field) => { data.inferenceId = inferenceValue; if (data.inferenceId === undefined) { return; } - const inferenceData = inferenceToModelIdMap?.[data.inferenceId]; - if (!inferenceData) { return; } - const { trainedModelId, defaultInferenceEndpoint, isDeployed, isDeployable } = inferenceData; + const { trainedModelId } = inferenceData; + dispatch({ type: 'field.addSemanticText', value: data }); - if (isDeployable && trainedModelId) { - try { - const modelDownloaded: boolean = await isModelDownloaded(trainedModelId); + try { + // if model exists already, do not create inference endpoint + const inferenceModels = await getInferenceModels(); + const inferenceModel: InferenceAPIConfigResponse[] = inferenceModels.data.some( + (e: InferenceAPIConfigResponse) => e.model_id === inferenceValue + ); + if (inferenceModel) { + return; + } - if (isDeployed) { - createInferenceEndpoint(trainedModelId, defaultInferenceEndpoint, data); - } else if (modelDownloaded) { - ml?.mlApi?.trainedModels - .startModelAllocation(trainedModelId) - .then(() => createInferenceEndpoint(trainedModelId, defaultInferenceEndpoint, data)); - } else { - ml?.mlApi?.trainedModels - .installElasticTrainedModelConfig(trainedModelId) - .then(() => ml?.mlApi?.trainedModels.startModelAllocation(trainedModelId)) - .then(() => createInferenceEndpoint(trainedModelId, defaultInferenceEndpoint, data)); - } - toasts?.addSuccess({ - title: i18n.translate( - 'xpack.idxMgmt.mappingsEditor.createField.modelDeploymentStartedNotification', - { - defaultMessage: 'Model deployment started', - } - ), - text: i18n.translate( - 'xpack.idxMgmt.mappingsEditor.createField.modelDeploymentNotification', - { - defaultMessage: '1 model is being deployed on your ml_node.', - } - ), - }); - } catch (error) { + if (trainedModelId) { + // show toasts only if it's elastic models + showSuccessToasts(); + } + + await createInferenceEndpoint(trainedModelId, data, customInferenceEndpointConfig); + } catch (error) { + // trainedModelId is empty string when it's a third party model + if (trainedModelId) { setErrorsInTrainedModelDeployment?.((prevItems) => [...prevItems, trainedModelId]); - toasts?.addError(error.body && error.body.message ? new Error(error.body.message) : error, { - title: i18n.translate( - 'xpack.idxMgmt.mappingsEditor.createField.modelDeploymentErrorTitle', - { - defaultMessage: 'Model deployment failed', - } - ), - }); } + showErrorToasts(error); } - - dispatch({ type: 'field.addSemanticText', value: data }); }; return { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx index ec6b3e9cabd34..0fc2e49d0a9cf 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx @@ -26,6 +26,7 @@ export const FIELD_TYPES_OPTIONS = Object.entries(MAIN_DATA_TYPE_DEFINITION).map ([dataType, { label }]) => ({ value: dataType, label, + 'data-test-subj': `fieldTypesOptions-${dataType}`, }) ) as ComboBoxOption[]; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts index 53f553f8659ad..767d29aaaeda8 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts @@ -7,6 +7,8 @@ import { ReactNode } from 'react'; +import { InferenceTaskType } from '@elastic/elasticsearch/lib/api/types'; +import { ModelConfig } from '@kbn/inference_integration_flyout'; import { GenericObject } from './mappings_editor'; import { PARAMETERS_DEFINITION } from '../constants'; @@ -246,3 +248,16 @@ export interface NormalizedRuntimeField { export interface NormalizedRuntimeFields { [id: string]: NormalizedRuntimeField; } +export enum DefaultInferenceModels { + elser_model_2 = 'elser_model_2', + e5 = 'e5', +} + +export enum DeploymentState { + 'DEPLOYED' = 'deployed', + 'NOT_DEPLOYED' = 'not_deployed', +} +export interface CustomInferenceEndpointConfig { + taskType: InferenceTaskType; + modelConfig: ModelConfig; +} diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/trained_models_deployment_modal.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/trained_models_deployment_modal.tsx index 4521a64c1dac4..8c2bfbbbef96d 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/trained_models_deployment_modal.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/trained_models_deployment_modal.tsx @@ -84,9 +84,9 @@ export function TrainedModelsDeploymentModal({ onCancel={closeModal} onConfirm={refreshModal} cancelButtonText={i18n.translate( - 'xpack.idxMgmt.indexDetails.trainedModelsDeploymentModal.cancelButtonLabel', + 'xpack.idxMgmt.indexDetails.trainedModelsDeploymentModal.closeButtonLabel', { - defaultMessage: 'Cancel', + defaultMessage: 'Close', } )} confirmButtonText={i18n.translate( diff --git a/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.test.ts b/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.test.ts index 98ecbb23b989a..1517b9664f3ea 100644 --- a/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.test.ts +++ b/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.test.ts @@ -104,13 +104,11 @@ const inferenceToModelIdMap = { trainedModelId: '.elser_model_2', isDeployed: true, isDeployable: true, - defaultInferenceEndpoint: false, }, e5: { trainedModelId: '.multilingual-e5-small', isDeployed: true, isDeployable: true, - defaultInferenceEndpoint: false, }, } as InferenceToModelIdMap; @@ -127,13 +125,11 @@ describe('useDetailsPageMappingsModelManagement', () => { value: { inferenceToModelIdMap: { e5: { - defaultInferenceEndpoint: false, isDeployed: false, isDeployable: true, trainedModelId: '.multilingual-e5-small', }, elser_model_2: { - defaultInferenceEndpoint: true, isDeployed: true, isDeployable: true, trainedModelId: '.elser_model_2', diff --git a/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.ts b/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.ts index fb27053d35547..38cf20b9bf534 100644 --- a/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.ts +++ b/x-pack/plugins/index_management/public/hooks/use_details_page_mappings_model_management.ts @@ -13,14 +13,18 @@ import { useAppContext } from '../application/app_context'; import { InferenceToModelIdMap } from '../application/components/mappings_editor/components/document_fields/fields'; import { deNormalize } from '../application/components/mappings_editor/lib'; import { useDispatch } from '../application/components/mappings_editor/mappings_state_context'; -import { NormalizedFields } from '../application/components/mappings_editor/types'; +import { + DefaultInferenceModels, + DeploymentState, + NormalizedFields, +} from '../application/components/mappings_editor/types'; import { getInferenceModels } from '../application/services/api'; interface InferenceModel { data: InferenceAPIConfigResponse[]; } -type DeploymentStatusType = Record; +type DeploymentStatusType = Record; const getCustomInferenceIdMap = ( deploymentStatsByModelId: DeploymentStatusType, @@ -39,7 +43,6 @@ const getCustomInferenceIdMap = ( trainedModelId, isDeployable: model.service === Service.elser || model.service === Service.elasticsearch, isDeployed: deploymentStatsByModelId[trainedModelId] === 'deployed', - defaultInferenceEndpoint: false, }; return inferenceMap; }, {}); @@ -50,7 +53,9 @@ export const getTrainedModelStats = (modelStats?: InferenceStatsResponse): Deplo modelStats?.trained_model_stats.reduce((acc, modelStat) => { if (modelStat.model_id) { acc[modelStat.model_id] = - modelStat?.deployment_stats?.state === 'started' ? 'deployed' : 'not_deployed'; + modelStat?.deployment_stats?.state === 'started' + ? DeploymentState.DEPLOYED + : DeploymentState.NOT_DEPLOYED; } return acc; }, {}) || {} @@ -59,17 +64,18 @@ export const getTrainedModelStats = (modelStats?: InferenceStatsResponse): Deplo const getDefaultInferenceIds = (deploymentStatsByModelId: DeploymentStatusType) => { return { - elser_model_2: { - trainedModelId: '.elser_model_2', + [DefaultInferenceModels.elser_model_2]: { + trainedModelId: ElasticsearchModelDefaultOptions.elser, isDeployable: true, - isDeployed: deploymentStatsByModelId['.elser_model_2'] === 'deployed', - defaultInferenceEndpoint: true, + isDeployed: + deploymentStatsByModelId[ElasticsearchModelDefaultOptions.elser] === + DeploymentState.DEPLOYED, }, - e5: { - trainedModelId: '.multilingual-e5-small', + [DefaultInferenceModels.e5]: { + trainedModelId: ElasticsearchModelDefaultOptions.e5, isDeployable: true, - isDeployed: deploymentStatsByModelId['.multilingual-e5-small'] === 'deployed', - defaultInferenceEndpoint: true, + isDeployed: + deploymentStatsByModelId[ElasticsearchModelDefaultOptions.e5] === DeploymentState.DEPLOYED, }, }; }; diff --git a/x-pack/plugins/index_management/public/hooks/use_ml_model_status_toasts.ts b/x-pack/plugins/index_management/public/hooks/use_ml_model_status_toasts.ts new file mode 100644 index 0000000000000..c9a0c37a37fc9 --- /dev/null +++ b/x-pack/plugins/index_management/public/hooks/use_ml_model_status_toasts.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { ErrorType, extractErrorProperties, MLRequestFailure } from '@kbn/ml-error-utils'; +import { useComponentTemplatesContext } from '../application/components/component_templates/component_templates_context'; + +export function useMLModelNotificationToasts() { + const { toasts } = useComponentTemplatesContext(); + const showSuccessToasts = () => { + return toasts.addSuccess({ + title: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.createField.modelDeploymentStartedNotification', + { + defaultMessage: 'Model deployment started', + } + ), + text: i18n.translate('xpack.idxMgmt.mappingsEditor.createField.modelDeploymentNotification', { + defaultMessage: '1 model is being deployed on your ml_node.', + }), + }); + }; + const showErrorToasts = (error: ErrorType) => { + const errorObj = extractErrorProperties(error); + return toasts.addError(new MLRequestFailure(errorObj, error), { + title: i18n.translate('xpack.idxMgmt.mappingsEditor.createField.modelDeploymentErrorTitle', { + defaultMessage: 'Model deployment failed', + }), + }); + }; + return { showSuccessToasts, showErrorToasts }; +} diff --git a/x-pack/plugins/index_management/tsconfig.json b/x-pack/plugins/index_management/tsconfig.json index 202a755a8b21d..ec199f7b11f53 100644 --- a/x-pack/plugins/index_management/tsconfig.json +++ b/x-pack/plugins/index_management/tsconfig.json @@ -49,9 +49,9 @@ "@kbn/utility-types", "@kbn/inference_integration_flyout", "@kbn/ml-plugin", - "@kbn/ml-error-utils", "@kbn/react-kibana-context-render", - "@kbn/react-kibana-mount" + "@kbn/react-kibana-mount", + "@kbn/ml-error-utils", ], "exclude": ["target/**/*"] } From e52750ff1d5e3ab227ffe46421c1439403f6aec4 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 18 Jun 2024 00:02:30 +0200 Subject: [PATCH 027/127] [Discover] Add deprecation badges to some of old Advanced Settings (#185871) - Closes https://github.com/elastic/kibana/issues/179899 ## Summary This PR adds deprecation badges to: - discover:searchFieldsFromSource - doc_table:legacy - rollups:enableIndexPatterns --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + src/plugins/discover/server/ui_settings.ts | 18 ++++++++++++++++++ x-pack/plugins/rollup/server/plugin.ts | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 00899f64f3d63..3fcd6df837c29 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -516,6 +516,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D : `${ELASTICSEARCH_DOCS}index-mgmt.html`, kibanaSearchSettings: `${KIBANA_DOCS}advanced-options.html#kibana-search-settings`, discoverSettings: `${KIBANA_DOCS}advanced-options.html#kibana-discover-settings`, + rollupSettings: `${KIBANA_DOCS}advanced-options.html#kibana-rollups-settings`, visualizationSettings: `${KIBANA_DOCS}advanced-options.html#kibana-visualization-settings`, timelionSettings: `${KIBANA_DOCS}advanced-options.html#kibana-timelion-settings`, savedObjectsApiList: `${KIBANA_DOCS}saved-objects-api.html#saved-objects-api`, diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index fab0d56c0d828..5e66e1f2252d1 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -207,6 +207,15 @@ export const getUiSettings: ( type: METRIC_TYPE.CLICK, name: 'discover:useLegacyDataGrid', }, + deprecation: { + message: i18n.translate( + 'discover.advancedSettings.discover.disableDocumentExplorerDeprecation', + { + defaultMessage: 'This setting is deprecated and will be removed in Kibana 9.0.', + } + ), + docLinksKey: 'discoverSettings', + }, }, [MODIFY_COLUMNS_ON_SWITCH]: { name: i18n.translate('discover.advancedSettings.discover.modifyColumnsOnSwitchTitle', { @@ -236,6 +245,15 @@ export const getUiSettings: ( value: false, category: ['discover'], schema: schema.boolean(), + deprecation: { + message: i18n.translate( + 'discover.advancedSettings.discover.readFieldsFromSourceDeprecation', + { + defaultMessage: 'This setting is deprecated and will be removed in Kibana 9.0.', + } + ), + docLinksKey: 'discoverSettings', + }, }, [SHOW_FIELD_STATISTICS]: { name: i18n.translate('discover.advancedSettings.discover.showFieldStatistics', { diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index ff8ff7e809b13..cd0a6835cd857 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -90,6 +90,12 @@ export class RollupPlugin implements Plugin { category: ['rollups'], schema: schema.boolean(), requiresPageReload: true, + deprecation: { + message: i18n.translate('xpack.rollupJobs.rollupDataViewsDeprecation', { + defaultMessage: 'This setting is deprecated and will be removed in Kibana 9.0.', + }), + docLinksKey: 'rollupSettings', + }, }, }); From f6943060f78cc590c9f94dd505ce6d85b8227e77 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 18 Jun 2024 07:08:09 +0200 Subject: [PATCH 028/127] [api-docs] 2024-06-18 Daily api_docs build (#186349) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/741 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- .../ai_assistant_management_selection.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/apm_data_access.mdx | 2 +- api_docs/asset_manager.mdx | 2 +- api_docs/assets_data_access.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_quality.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/dataset_quality.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 4 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/discover_shared.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/elastic_assistant.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/esql_data_grid.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_annotation_listing.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/fields_metadata.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 34 +++++-- api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/ingest_pipelines.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/integration_assistant.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/investigate.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_actions_types.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_log_pattern_analysis.mdx | 2 +- api_docs/kbn_aiops_log_rate_analysis.mdx | 2 +- .../kbn_alerting_api_integration_helpers.mdx | 2 +- api_docs/kbn_alerting_comparators.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerting_types.mdx | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- api_docs/kbn_analytics_collection_utils.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_data_view.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_bfetch_error.mdx | 2 +- api_docs/kbn_calculate_auto.mdx | 2 +- .../kbn_calculate_width_from_char_count.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mock.mdx | 2 +- api_docs/kbn_code_owners.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...tent_management_table_list_view_common.mdx | 2 +- ...ntent_management_table_list_view_table.mdx | 2 +- api_docs/kbn_content_management_utils.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- .../kbn_core_plugins_contracts_browser.mdx | 2 +- .../kbn_core_plugins_contracts_server.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_security_browser.mdx | 2 +- .../kbn_core_security_browser_internal.mdx | 2 +- api_docs/kbn_core_security_browser_mocks.mdx | 2 +- api_docs/kbn_core_security_common.mdx | 2 +- api_docs/kbn_core_security_server.mdx | 2 +- .../kbn_core_security_server_internal.mdx | 2 +- api_docs/kbn_core_security_server_mocks.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- .../kbn_core_test_helpers_model_versions.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_browser.mdx | 2 +- ...kbn_core_user_profile_browser_internal.mdx | 2 +- .../kbn_core_user_profile_browser_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_common.mdx | 2 +- api_docs/kbn_core_user_profile_server.mdx | 2 +- .../kbn_core_user_profile_server_internal.mdx | 2 +- .../kbn_core_user_profile_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_custom_icons.mdx | 2 +- api_docs/kbn_custom_integrations.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_forge.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_data_stream_adapter.mdx | 2 +- api_docs/kbn_data_view_utils.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_fleet.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_deeplinks_security.mdx | 2 +- api_docs/kbn_deeplinks_shared.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.mdx | 2 +- api_docs/kbn_doc_links.devdocs.json | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_agent_utils.mdx | 2 +- api_docs/kbn_elastic_assistant.mdx | 2 +- api_docs/kbn_elastic_assistant_common.mdx | 2 +- api_docs/kbn_entities_schema.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_esql_ast.mdx | 2 +- api_docs/kbn_esql_utils.mdx | 2 +- api_docs/kbn_esql_validation_autocomplete.mdx | 2 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_field_utils.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_formatters.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- .../kbn_ftr_common_functional_ui_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_grouping.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_index_management.mdx | 2 +- api_docs/kbn_inference_integration_flyout.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_ipynb.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_lens_embeddable_utils.mdx | 2 +- api_docs/kbn_lens_formula_docs.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_content_badge.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- .../kbn_management_settings_application.mdx | 2 +- ...ent_settings_components_field_category.mdx | 2 +- ...gement_settings_components_field_input.mdx | 2 +- ...nagement_settings_components_field_row.mdx | 2 +- ...bn_management_settings_components_form.mdx | 2 +- ...n_management_settings_field_definition.mdx | 2 +- api_docs/kbn_management_settings_ids.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_settings_types.mdx | 2 +- .../kbn_management_settings_utilities.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_cancellable_search.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- api_docs/kbn_ml_chi2test.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_in_memory_table.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_time_buckets.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_ui_actions.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_mock_idp_utils.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- .../kbn_observability_alerting_test_data.mdx | 2 +- ...ility_get_padded_alert_time_range_util.mdx | 2 +- api_docs/kbn_openapi_bundler.mdx | 2 +- api_docs/kbn_openapi_generator.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- api_docs/kbn_panel_loader.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_check.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_presentation_containers.mdx | 2 +- api_docs/kbn_presentation_publishing.mdx | 2 +- api_docs/kbn_profiling_utils.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_react_hooks.mdx | 2 +- api_docs/kbn_react_kibana_context_common.mdx | 2 +- api_docs/kbn_react_kibana_context_render.mdx | 2 +- api_docs/kbn_react_kibana_context_root.mdx | 2 +- api_docs/kbn_react_kibana_context_styled.mdx | 2 +- api_docs/kbn_react_kibana_context_theme.mdx | 2 +- api_docs/kbn_react_kibana_mount.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_reporting_csv_share_panel.mdx | 2 +- api_docs/kbn_reporting_export_types_csv.mdx | 2 +- .../kbn_reporting_export_types_csv_common.mdx | 2 +- api_docs/kbn_reporting_export_types_pdf.mdx | 2 +- .../kbn_reporting_export_types_pdf_common.mdx | 2 +- api_docs/kbn_reporting_export_types_png.mdx | 2 +- .../kbn_reporting_export_types_png_common.mdx | 2 +- api_docs/kbn_reporting_mocks_server.mdx | 2 +- api_docs/kbn_reporting_public.mdx | 2 +- api_docs/kbn_reporting_server.mdx | 2 +- api_docs/kbn_resizable_layout.mdx | 2 +- .../kbn_response_ops_feature_flag_service.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_router_to_openapispec.mdx | 2 +- api_docs/kbn_router_utils.mdx | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_search_api_panels.mdx | 2 +- api_docs/kbn_search_connectors.mdx | 2 +- api_docs/kbn_search_errors.mdx | 2 +- api_docs/kbn_search_index_documents.mdx | 2 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_search_types.mdx | 2 +- api_docs/kbn_security_hardening.mdx | 2 +- api_docs/kbn_security_plugin_types_common.mdx | 2 +- api_docs/kbn_security_plugin_types_public.mdx | 2 +- ..._security_plugin_types_server.devdocs.json | 40 ++++----- api_docs/kbn_security_plugin_types_server.mdx | 2 +- api_docs/kbn_security_solution_features.mdx | 2 +- api_docs/kbn_security_solution_navigation.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_serverless_common_settings.mdx | 2 +- .../kbn_serverless_observability_settings.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_search_settings.mdx | 2 +- api_docs/kbn_serverless_security_settings.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_error_boundary.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_tabbed_modal.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.devdocs.json | 88 ++++++++++--------- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_predicates.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.devdocs.json | 36 +++++++- api_docs/kbn_test.mdx | 4 +- api_docs/kbn_test_eui_helpers.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_timerange.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_triggers_actions_ui_types.mdx | 2 +- api_docs/kbn_try_in_console.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_data_table.mdx | 2 +- api_docs/kbn_unified_doc_viewer.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_unsaved_changes_badge.mdx | 2 +- api_docs/kbn_unsaved_changes_prompt.mdx | 2 +- api_docs/kbn_use_tracked_promise.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_visualization_utils.mdx | 2 +- api_docs/kbn_xstate_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kbn_zod_helpers.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/links.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/logs_data_access.mdx | 2 +- api_docs/logs_explorer.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/metrics_data_access.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/mock_idp_plugin.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/no_data_page.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_a_i_assistant_app.mdx | 2 +- .../observability_ai_assistant_management.mdx | 2 +- api_docs/observability_logs_explorer.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/painless_lab.mdx | 2 +- api_docs/plugin_directory.mdx | 8 +- api_docs/presentation_panel.mdx | 2 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/profiling_data_access.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/search_connectors.mdx | 2 +- api_docs/search_inference_endpoints.mdx | 2 +- api_docs/search_notebooks.mdx | 2 +- api_docs/search_playground.mdx | 2 +- api_docs/security.devdocs.json | 40 ++++----- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/slo.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/text_based_languages.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_doc_viewer.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/uptime.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 705 files changed, 854 insertions(+), 796 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index e669f6344efe4..624022104e4b5 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: 2024-06-17 +date: 2024-06-18 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 e4ce3d3d809f4..779596da4321e 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index ad899d5b30fa7..48d70e70a5982 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 9fef5c6dbd430..6589c58e34397 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: 2024-06-17 +date: 2024-06-18 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 5e1523e0a3842..a158e8daac03a 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: 2024-06-17 +date: 2024-06-18 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 d6b614ee1d744..aa4431dbb04da 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 5fe9a4777bcc7..3e2cc9fefafc0 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 51ec9eba5b862..2d1ba34fc9aaa 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/assets_data_access.mdx b/api_docs/assets_data_access.mdx index 50feaddd919fb..3ee0d44d975bd 100644 --- a/api_docs/assets_data_access.mdx +++ b/api_docs/assets_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetsDataAccess title: "assetsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the assetsDataAccess plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetsDataAccess'] --- import assetsDataAccessObj from './assets_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 1535f0fdb0549..fb0a9a20e575c 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: 2024-06-17 +date: 2024-06-18 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 00bee7c4b9bc5..393d71d9328ce 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: 2024-06-17 +date: 2024-06-18 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 de7aca323a1b1..7c71ac4bfb55e 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: 2024-06-17 +date: 2024-06-18 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 0748b61b123c8..c29e6f64f1930 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: 2024-06-17 +date: 2024-06-18 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 634b1e16398dc..ca4066e185d27 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: 2024-06-17 +date: 2024-06-18 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 1b1693299fe3d..b1e7c01136a03 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 36756a7e7d23d..69ff8dc302a53 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: 2024-06-17 +date: 2024-06-18 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 88223862d4f6d..79bf2006480fd 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: 2024-06-17 +date: 2024-06-18 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 df95c8ca9604f..e540ca3c9d751 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: 2024-06-17 +date: 2024-06-18 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 d6421a40ce532..307768caee6aa 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: 2024-06-17 +date: 2024-06-18 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 996aa6c999ae8..31535c63a5280 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: 2024-06-17 +date: 2024-06-18 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 6d69b349cc2ca..51ec36c9a0e93 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: 2024-06-17 +date: 2024-06-18 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 aac1852d986db..61fad6567819c 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: 2024-06-17 +date: 2024-06-18 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 fe8a893b471de..55e65c72384d8 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: 2024-06-17 +date: 2024-06-18 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 1a30d17f3db46..dd62d55494171 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: 2024-06-17 +date: 2024-06-18 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 61c87fd0e0286..d2b741e32aed6 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index b8539d3b9a861..b8bd937dbe6c2 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx index 9f7fe6b7fba4e..4d138efed58ae 100644 --- a/api_docs/data_quality.mdx +++ b/api_docs/data_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality title: "dataQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the dataQuality plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality'] --- import dataQualityObj from './data_quality.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index ea9672a7a2ef7..ff7b36e487175 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: 2024-06-17 +date: 2024-06-18 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 e49d31bb27213..066c7271b7b52 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: 2024-06-17 +date: 2024-06-18 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 9658b11938c7b..296636689811f 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: 2024-06-17 +date: 2024-06-18 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 14345fff79b2c..94ebc7428bc25 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: 2024-06-17 +date: 2024-06-18 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 3c47bb01bfdcf..4cc110a02ed31 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 6d9cc8fbb6606..23caaad9e7d54 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: 2024-06-17 +date: 2024-06-18 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 7555c40986953..f30163d4e24d1 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 8ed0ba095ef18..7f3ddaf93dd5e 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 2b7977e2526ae..c810331094fbb 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index e7ee880cdf970..7f17da6336fad 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -860,7 +860,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [use_get_logs_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx#:~:text=indexPatternId) | - | | | [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode) | 8.8.0 | | | [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode) | 8.8.0 | -| | [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/security/security.ts#:~:text=authc), [transform_api_keys.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/api_keys/transform_api_keys.ts#:~:text=authc), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/api_keys/security.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc)+ 36 more | - | +| | [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/api_keys/security.ts#:~:text=authc), [security.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/security/security.ts#:~:text=authc), [transform_api_keys.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/api_keys/transform_api_keys.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/epm/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts#:~:text=authc), [handlers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts#:~:text=authc)+ 36 more | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/integrations/index.tsx#:~:text=appBasePath) | 8.8.0 | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/saved_objects/index.ts#:~:text=migrations), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/saved_objects/index.ts#:~:text=migrations) | - | | | [audit_logging.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/audit_logging.ts#:~:text=audit), [audit_logging.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/audit_logging.ts#:~:text=audit) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index e2a11bb37fbee..73a33c4668a80 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index b1acedbda0788..953a9839ff37a 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: 2024-06-17 +date: 2024-06-18 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 8d22aab285ac8..e364ccc82a307 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: 2024-06-17 +date: 2024-06-18 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 b47659da336f7..c77515d70677e 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx index 21118b394b1f0..915e355fd79e4 100644 --- a/api_docs/discover_shared.mdx +++ b/api_docs/discover_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared title: "discoverShared" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverShared plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared'] --- import discoverSharedObj from './discover_shared.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index b5a2b4407a973..1a6f9e9575cd9 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index ddefb78f3f8ca..441403cde9067 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 78357e670b1d3..76871e6e68083 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: 2024-06-17 +date: 2024-06-18 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 d379600205003..e04871b3b1db9 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: 2024-06-17 +date: 2024-06-18 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 6dc6fa126e5cb..8d9ac94478971 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: 2024-06-17 +date: 2024-06-18 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 7b9bc0486ac5a..1f3003a64cb9b 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: 2024-06-17 +date: 2024-06-18 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 085d9250db7d2..8108a8b6776ee 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index 72031c874283e..529e5bfc24b8c 100644 --- a/api_docs/esql_data_grid.mdx +++ b/api_docs/esql_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esqlDataGrid title: "esqlDataGrid" image: https://source.unsplash.com/400x175/?github description: API docs for the esqlDataGrid plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esqlDataGrid'] --- import esqlDataGridObj from './esql_data_grid.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 18f08b3836801..1c9e14ba90492 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 8f278710bd260..d45db1f6914e6 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index f80eb5d14ca36..da36e99e65ca2 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 9fb1c4a93b73d..0025d08edc171 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 46b2d052a25ee..01eafa01dee30 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: 2024-06-17 +date: 2024-06-18 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 2f6494cdace31..925852e77d69b 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: 2024-06-17 +date: 2024-06-18 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 c299a0d3d34ab..8aa5f4462cf5f 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: 2024-06-17 +date: 2024-06-18 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 c0b7995afcb51..bba400d1b3045 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: 2024-06-17 +date: 2024-06-18 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 b3e5312e8410c..1a303f42e9638 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: 2024-06-17 +date: 2024-06-18 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 4f2f34f6bbd6e..0ffcf4d1ee5bd 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: 2024-06-17 +date: 2024-06-18 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 ffa7aae0cf672..305b36fdb6207 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: 2024-06-17 +date: 2024-06-18 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 b11b0ba0073d4..0cbea72f7563c 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: 2024-06-17 +date: 2024-06-18 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 4670ef58d76c5..c35b81f908315 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: 2024-06-17 +date: 2024-06-18 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 90563de6cee2e..78a57072b2ae2 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: 2024-06-17 +date: 2024-06-18 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 ac420ce8974ed..3fa4ac3f62b0f 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: 2024-06-17 +date: 2024-06-18 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 6ab9a7d1674ce..4452aa394f13c 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: 2024-06-17 +date: 2024-06-18 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 39aa22a1e86b9..626bd0655b3dc 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: 2024-06-17 +date: 2024-06-18 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 3a884971b1b90..ad99535b03f13 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: 2024-06-17 +date: 2024-06-18 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 0b4da5be483d7..a319f1537ccf5 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: 2024-06-17 +date: 2024-06-18 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 cbad887301cc2..bb88bdc3705a7 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/fields_metadata.mdx b/api_docs/fields_metadata.mdx index 4154fe2cd85f1..ce996ad370aa5 100644 --- a/api_docs/fields_metadata.mdx +++ b/api_docs/fields_metadata.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldsMetadata title: "fieldsMetadata" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldsMetadata plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldsMetadata'] --- import fieldsMetadataObj from './fields_metadata.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index ace9a985bc18b..790b8fc5cff15 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: 2024-06-17 +date: 2024-06-18 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 5c0bee1ea0c59..a2fd13d1c9964 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: 2024-06-17 +date: 2024-06-18 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 2356f96b7cd32..5147aec2df8ab 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 4cae24c9356cc..eccb9aef35f1b 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -3384,10 +3384,10 @@ "id": "def-public.UIExtensionsStorage.Unnamed", "type": "IndexSignature", "tags": [], - "label": "[key: string]: Partial>", + "label": "[key: string]: Partial>", "description": [], "signature": [ - "[key: string]: Partial | undefined; aggregations?: Record | undefined; }>" ], @@ -21293,6 +21299,22 @@ "path": "x-pack/plugins/fleet/common/types/models/agent.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.FleetServerAgent.namespaces", + "type": "Array", + "tags": [], + "label": "namespaces", + "description": [ + "\nNamespaces" + ], + "signature": [ + "string[] | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/agent.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 85574cf7f3c98..75c84f6c1d72b 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1337 | 5 | 1216 | 71 | +| 1338 | 5 | 1216 | 72 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 76624d27343ab..215446f0c0bb3 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: 2024-06-17 +date: 2024-06-18 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 8f8c66cf87d7d..a86418e1b03d6 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: 2024-06-17 +date: 2024-06-18 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 b4abbc90b216f..d08cb4c662cf9 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: 2024-06-17 +date: 2024-06-18 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 d23eecf1080b7..1025665cd37ed 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: 2024-06-17 +date: 2024-06-18 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 d07eb6950d5b4..03bb198df26a7 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: 2024-06-17 +date: 2024-06-18 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 313b2019871f5..1942fce8dc4b3 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: 2024-06-17 +date: 2024-06-18 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 5e5e50c45f4ea..adf5bec595e95 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index fb90e61284459..fbf0e38e34f54 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index b950ff6404005..14af91942d5bb 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/integration_assistant.mdx b/api_docs/integration_assistant.mdx index bb862840a8d1d..3843c88387c92 100644 --- a/api_docs/integration_assistant.mdx +++ b/api_docs/integration_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/integrationAssistant title: "integrationAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the integrationAssistant plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'integrationAssistant'] --- import integrationAssistantObj from './integration_assistant.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index ec0a89a966912..357d85637bd47 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index 4d93088efa878..8de337c3c95d4 100644 --- a/api_docs/investigate.mdx +++ b/api_docs/investigate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigate title: "investigate" image: https://source.unsplash.com/400x175/?github description: API docs for the investigate plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 7ce881579a5a7..b06c821e80cda 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index b02a2a9d21a6a..fa8abc5d1abe4 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index e1a8e798f160c..01e342ac33cb7 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_pattern_analysis.mdx b/api_docs/kbn_aiops_log_pattern_analysis.mdx index 72eede9d9fd82..ff4acdfbeb759 100644 --- a/api_docs/kbn_aiops_log_pattern_analysis.mdx +++ b/api_docs/kbn_aiops_log_pattern_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-pattern-analysis title: "@kbn/aiops-log-pattern-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-pattern-analysis plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-pattern-analysis'] --- import kbnAiopsLogPatternAnalysisObj from './kbn_aiops_log_pattern_analysis.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_rate_analysis.mdx b/api_docs/kbn_aiops_log_rate_analysis.mdx index b6589e7e5c8a6..ec680f789947b 100644 --- a/api_docs/kbn_aiops_log_rate_analysis.mdx +++ b/api_docs/kbn_aiops_log_rate_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-rate-analysis title: "@kbn/aiops-log-rate-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-rate-analysis plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-rate-analysis'] --- import kbnAiopsLogRateAnalysisObj from './kbn_aiops_log_rate_analysis.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index b30d9b247986a..227b93cbe6c80 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_comparators.mdx b/api_docs/kbn_alerting_comparators.mdx index 3ff7cd7b524ea..e8909afd96cd6 100644 --- a/api_docs/kbn_alerting_comparators.mdx +++ b/api_docs/kbn_alerting_comparators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-comparators title: "@kbn/alerting-comparators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-comparators plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-comparators'] --- import kbnAlertingComparatorsObj from './kbn_alerting_comparators.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 59f71bb7d06a4..7162776bea72e 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index 1fa5967e92c76..df3d3c1ebde23 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 0f54660851da3..4abb587516915 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 6a8ace9a32049..487d845867b34 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: 2024-06-17 +date: 2024-06-18 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 f61a72c328c9f..e46bfe5940a94 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: 2024-06-17 +date: 2024-06-18 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 f9e06eed6bb64..45cdad52bc478 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index fc3bb389ac23d..351c1e8690d63 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.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 8a10802899033..a1fc062137334 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: 2024-06-17 +date: 2024-06-18 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 555450cec3ae8..530d29f8d6ee8 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: 2024-06-17 +date: 2024-06-18 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 64e8755f22ef9..536f741488ff9 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: 2024-06-17 +date: 2024-06-18 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 7ff9f68c236d5..6d5fbaf58357b 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index bfdfd2f4f74c5..d98fbe3570141 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: 2024-06-17 +date: 2024-06-18 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_data_view.mdx b/api_docs/kbn_apm_data_view.mdx index 42348387533e9..307aeb06fe7b0 100644 --- a/api_docs/kbn_apm_data_view.mdx +++ b/api_docs/kbn_apm_data_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-data-view title: "@kbn/apm-data-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-data-view plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-data-view'] --- import kbnApmDataViewObj from './kbn_apm_data_view.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 27d6759bd2561..d16fad88bde1c 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: 2024-06-17 +date: 2024-06-18 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 9f40bdce1dbdc..5d4077f25f851 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: 2024-06-17 +date: 2024-06-18 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 4763291740a71..4078b2b992498 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: 2024-06-17 +date: 2024-06-18 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 2f3bee6b0080b..a86bfa4aba3dc 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index c616928926410..dfab0800e2a0f 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 92dc69482554b..a831688cd6a16 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index 4f2c217badd05..56e46c2ac595e 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 113c5038fcdd3..88e2fe42a4fec 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: 2024-06-17 +date: 2024-06-18 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 23dab4eb264dd..43e66d95034f7 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: 2024-06-17 +date: 2024-06-18 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 e4b859e84188f..73f3e636779ac 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: 2024-06-17 +date: 2024-06-18 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 36c62cf75e461..a39b164e2e066 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: 2024-06-17 +date: 2024-06-18 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 af73a6f2672b0..7b14acf65b838 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: 2024-06-17 +date: 2024-06-18 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 4aa785c60d7f2..ed9607d16f834 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: 2024-06-17 +date: 2024-06-18 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 5e7638dad0389..a8c36eed58e93 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: 2024-06-17 +date: 2024-06-18 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 a47825df146d7..cf0dac9edba01 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: 2024-06-17 +date: 2024-06-18 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 f0f1803d1d9fc..dfa158ac1ec18 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mock.mdx b/api_docs/kbn_code_editor_mock.mdx index 2c0792fd28f0f..54c2b42c47d0f 100644 --- a/api_docs/kbn_code_editor_mock.mdx +++ b/api_docs/kbn_code_editor_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mock title: "@kbn/code-editor-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mock plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mock'] --- import kbnCodeEditorMockObj from './kbn_code_editor_mock.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index 3517204bd45b1..a4509947484f8 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 3b1af9d2a8170..1ad88c024bbf8 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: 2024-06-17 +date: 2024-06-18 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 6502279e9947e..9b875d1e2e2ac 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: 2024-06-17 +date: 2024-06-18 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 dcaaa854f0382..e0e354ab7ad5d 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: 2024-06-17 +date: 2024-06-18 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 3d675e06d2fcc..bb15023427226 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: 2024-06-17 +date: 2024-06-18 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 f60a3981386a2..37dd4c0061cc2 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: 2024-06-17 +date: 2024-06-18 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_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index 8a4e4c5955ef6..b472318320313 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index 36028ba05cfa8..5b851e5384110 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index 805f07c38bf79..eaacdb815fed9 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index ee635383e39cd..b204e4dbf8374 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index 20536a7d3bad8..95d831172342a 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 54ae0bad6081e..5e8fb7e681138 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: 2024-06-17 +date: 2024-06-18 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 edfc4a38ef36f..79058a9a104e2 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: 2024-06-17 +date: 2024-06-18 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 1118dc0bff1c0..6c6b2b592bb48 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: 2024-06-17 +date: 2024-06-18 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 8b08b6e8f6004..b1281d75c3b3d 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: 2024-06-17 +date: 2024-06-18 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 4afef1d927b97..7de21c211151c 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: 2024-06-17 +date: 2024-06-18 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 eccfc56adb329..713977cd2472c 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: 2024-06-17 +date: 2024-06-18 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 60950431b91bf..f251d7a1c9350 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: 2024-06-17 +date: 2024-06-18 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 65de855ca3ee7..f981d646c6fb3 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: 2024-06-17 +date: 2024-06-18 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 a8da82ee1bef5..bef8995e9654b 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: 2024-06-17 +date: 2024-06-18 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 24f0cfed4a457..16145d3c11faf 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: 2024-06-17 +date: 2024-06-18 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 6028c3344a776..18fcb5acd1646 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: 2024-06-17 +date: 2024-06-18 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 a56db7522934e..e08586791cb80 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: 2024-06-17 +date: 2024-06-18 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 4ff38183b9eac..b295697eba559 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: 2024-06-17 +date: 2024-06-18 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 aaef90a451f78..eee3e8ec637f9 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: 2024-06-17 +date: 2024-06-18 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 bfdd1e2df9b27..94aacc78b60c1 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: 2024-06-17 +date: 2024-06-18 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 8e7da7d8d609e..970a80356039f 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: 2024-06-17 +date: 2024-06-18 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 d8c8bba1ba479..a3ee47d6811bf 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: 2024-06-17 +date: 2024-06-18 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 b838e24edeea9..1b9697f69616d 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: 2024-06-17 +date: 2024-06-18 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 20fc610aa4381..30cceca53d2eb 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: 2024-06-17 +date: 2024-06-18 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 4d5af3e83a817..cc6cb4c39c1c2 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: 2024-06-17 +date: 2024-06-18 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 5cba8debee929..12c6007f62848 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: 2024-06-17 +date: 2024-06-18 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 687bbc4fe712e..df65336afe538 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: 2024-06-17 +date: 2024-06-18 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 c25ff5885aa26..5381f189870cb 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: 2024-06-17 +date: 2024-06-18 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 f774814ff20f3..6794b366689c1 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: 2024-06-17 +date: 2024-06-18 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 0a3ed60dd03cf..4ff34e4adefc2 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: 2024-06-17 +date: 2024-06-18 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 e272909a893d1..e81870b643c87 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: 2024-06-17 +date: 2024-06-18 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 67938b5aa490c..6617eb567d073 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: 2024-06-17 +date: 2024-06-18 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 545d7ac729623..d84a80e9e697b 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: 2024-06-17 +date: 2024-06-18 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 bc6a970b2a23c..7b61b93bf6cc9 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: 2024-06-17 +date: 2024-06-18 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 c786d9af3f46e..31cfa4d4e45f9 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: 2024-06-17 +date: 2024-06-18 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 d6598828b3dad..bf2dd1174975c 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: 2024-06-17 +date: 2024-06-18 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 b105bd2524d97..2c5c656d5a173 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: 2024-06-17 +date: 2024-06-18 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 6acaff9e71065..0eef07d37f2f6 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: 2024-06-17 +date: 2024-06-18 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 fb76520008b47..c48a04beced54 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: 2024-06-17 +date: 2024-06-18 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 5474924b12a23..368228a724450 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: 2024-06-17 +date: 2024-06-18 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 bfaac5d4c2911..189c9acfe34dc 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: 2024-06-17 +date: 2024-06-18 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 d9897bcbb6457..4f27d9d7bdc27 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: 2024-06-17 +date: 2024-06-18 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 6ee40f9d97e54..a6780bf1df2ea 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: 2024-06-17 +date: 2024-06-18 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 634e3f9e13374..40fdbe57f7aec 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: 2024-06-17 +date: 2024-06-18 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 24926823d958b..90d2f8adc9c27 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: 2024-06-17 +date: 2024-06-18 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 487937b9b0f28..347b7e5ca7372 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: 2024-06-17 +date: 2024-06-18 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 588c1dda6a075..1d06db5d65017 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: 2024-06-17 +date: 2024-06-18 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 0714d977d7c3a..dffaee0aef227 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: 2024-06-17 +date: 2024-06-18 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 0b86a9c512fde..078d393221f85 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: 2024-06-17 +date: 2024-06-18 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 3ba50b8dac16d..1b33d6e1e1d43 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: 2024-06-17 +date: 2024-06-18 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 da80cfb3311b5..78c2fb36d6e18 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: 2024-06-17 +date: 2024-06-18 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 9ac7f069b22a1..81c7b543e5a39 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: 2024-06-17 +date: 2024-06-18 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 ca8f782cf8fdb..e9c8b9fb706e4 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: 2024-06-17 +date: 2024-06-18 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 7e658cb729e0e..201c9d3d19e46 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: 2024-06-17 +date: 2024-06-18 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 f98419701821e..3a7e7795ab0de 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: 2024-06-17 +date: 2024-06-18 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 6ea0c9944d1fa..56201fe91ba97 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: 2024-06-17 +date: 2024-06-18 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 2ee9ef3b28c0b..d8f2b10177c2a 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: 2024-06-17 +date: 2024-06-18 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 dce842b6af2bb..2b252e07e3385 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: 2024-06-17 +date: 2024-06-18 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 bac03638177b9..66a96931f2fcc 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: 2024-06-17 +date: 2024-06-18 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 9644cfce33b38..dab20d8cc1900 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: 2024-06-17 +date: 2024-06-18 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 cba891baf2822..0563ccd1b8165 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: 2024-06-17 +date: 2024-06-18 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 fe9b84a3c3217..12072174cb8f0 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: 2024-06-17 +date: 2024-06-18 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 dc698f6bc28ab..acef91e377e5e 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: 2024-06-17 +date: 2024-06-18 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 b0e6c6e4c27c4..6cd249cc3e4df 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: 2024-06-17 +date: 2024-06-18 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 18144b1e9448b..4e94ae5e5a8f1 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: 2024-06-17 +date: 2024-06-18 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 ddd4fbfe4177a..6c1070c0eaf01 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: 2024-06-17 +date: 2024-06-18 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 018af3ce1b385..8fc34ad8c65e1 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: 2024-06-17 +date: 2024-06-18 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 01ffe71663370..44fc25a15d19e 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: 2024-06-17 +date: 2024-06-18 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 d638b044dad2a..abb6ef5226309 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_http_resources_server.mdx index cab6799bff0b3..dcca80ea28e06 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: 2024-06-17 +date: 2024-06-18 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 4c12f16c2a8ea..509693ecd745a 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 71549eaf13b6f..8a70bb7f215a6 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index c3373fbd0c027..c7b81733f4991 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 132723544a715..ee3e10bf45147 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_http_server.mdx index a02429ead643f..c59369bdb598a 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 54fc0400180d9..94a84e11ee872 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: 2024-06-17 +date: 2024-06-18 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 a66c00bf85050..398c4b490aeff 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: 2024-06-17 +date: 2024-06-18 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 308810c2f34db..cef2050e92def 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: 2024-06-17 +date: 2024-06-18 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 f3f58f1e598be..a0e66b8eab87c 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: 2024-06-17 +date: 2024-06-18 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 ad5674f53c4ae..5fc017df1af97 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: 2024-06-17 +date: 2024-06-18 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 7d14a5df1cac9..7942a398e549b 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: 2024-06-17 +date: 2024-06-18 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 940c59e35302f..95e656990580d 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: 2024-06-17 +date: 2024-06-18 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 2cd31138fa05b..00307bd30d48f 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: 2024-06-17 +date: 2024-06-18 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 a1fb8ddc8f01a..9a3d9633892ee 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: 2024-06-17 +date: 2024-06-18 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 984367351f0a0..30f7e9f75dbfc 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: 2024-06-17 +date: 2024-06-18 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 7a21a00654041..b0c301e1425d0 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: 2024-06-17 +date: 2024-06-18 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 5a462ff9dd9b2..ddec0ce7847f4 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: 2024-06-17 +date: 2024-06-18 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 cb87edb50dd30..7ec9130a81c25 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: 2024-06-17 +date: 2024-06-18 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 13631df322a0c..9d93dec58ef0b 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: 2024-06-17 +date: 2024-06-18 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 781c290efa830..d75280e591054 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: 2024-06-17 +date: 2024-06-18 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 d01c51fedc371..1528d1873342d 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_logging_server.mdx index c803551f96ee7..a9e1c8beb172a 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 911eca5d9eacf..09c173f792ef9 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: 2024-06-17 +date: 2024-06-18 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 12d3f8850d6d3..272ce8ea971a3 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: 2024-06-17 +date: 2024-06-18 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 a3f43b920d875..767835c5efb7d 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: 2024-06-17 +date: 2024-06-18 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 7f3cf59bd5250..7f46853993532 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: 2024-06-17 +date: 2024-06-18 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 1588ea886fcd2..741ada6511119 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: 2024-06-17 +date: 2024-06-18 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 1d3b030a44635..20cc76f5b09ef 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: 2024-06-17 +date: 2024-06-18 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 45da69c906fc3..e99b6d6168e72 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: 2024-06-17 +date: 2024-06-18 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 1827a3566ec82..0214af178c9f0 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: 2024-06-17 +date: 2024-06-18 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 e921adbc4a2e3..65540f3457897 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: 2024-06-17 +date: 2024-06-18 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 f943b333f9792..61f89ff5f2cb3 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: 2024-06-17 +date: 2024-06-18 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 80e3a0fbda28f..ec3d7f9b86129 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: 2024-06-17 +date: 2024-06-18 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 ca2ee8d57e1b0..79310036bbe9a 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: 2024-06-17 +date: 2024-06-18 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 09b9d84416b03..a3998cca34a3a 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: 2024-06-17 +date: 2024-06-18 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 2bc91692e377f..45310c0840b60 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: 2024-06-17 +date: 2024-06-18 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 37f8d8d8565fa..c85edd3257f91 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: 2024-06-17 +date: 2024-06-18 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 52a6975ec0339..3393b2a402121 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: 2024-06-17 +date: 2024-06-18 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 64617ce924172..5d69b7ee580e0 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: 2024-06-17 +date: 2024-06-18 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 b7af11e6f7f58..f0cae503b4f1c 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: 2024-06-17 +date: 2024-06-18 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 b7309fd307623..99d1abe125a68 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: 2024-06-17 +date: 2024-06-18 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_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index b3f413fd8b804..6c97ce67d86a4 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index 96c99c1dec097..88aba70f77925 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 2819726083c7e..247f7c8135214 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: 2024-06-17 +date: 2024-06-18 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 9fe038fd41f71..0810e0ba2d759 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: 2024-06-17 +date: 2024-06-18 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 ce5a941529246..a1ad60f25d392 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: 2024-06-17 +date: 2024-06-18 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 c6b8a7cfcaef0..f20648b50a0b1 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: 2024-06-17 +date: 2024-06-18 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 4e99f055d2e1d..5de01f17af371 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: 2024-06-17 +date: 2024-06-18 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 ada8d4c859f55..5fb49017a9158 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: 2024-06-17 +date: 2024-06-18 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 15ca4c2aad1a2..4291832fd0738 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: 2024-06-17 +date: 2024-06-18 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 0a43ac9803d0a..a6dcf012a3253 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: 2024-06-17 +date: 2024-06-18 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 67b30a802e9b6..fba55c27a9059 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: 2024-06-17 +date: 2024-06-18 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 7dbb108d55d25..1f4246ce25225 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: 2024-06-17 +date: 2024-06-18 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_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index d1f83921f9988..c313d47ec8a2f 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: 2024-06-17 +date: 2024-06-18 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 acf4f86f23f46..df005b36ab161 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: 2024-06-17 +date: 2024-06-18 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 fc17a91ed817c..6a03625c7cbec 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: 2024-06-17 +date: 2024-06-18 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 803a3105865ab..ebe9f47d41e46 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: 2024-06-17 +date: 2024-06-18 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 88af27b56f3d2..2eddae6645152 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: 2024-06-17 +date: 2024-06-18 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 621a80d312fc2..820ca0283b29e 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_core_saved_objects_common.mdx index e56f6b4af841f..b4ba29e7cd7ac 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: 2024-06-17 +date: 2024-06-18 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 bad755357fef8..318f934666135 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: 2024-06-17 +date: 2024-06-18 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 003b968a38306..61bd3b20ba212 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: 2024-06-17 +date: 2024-06-18 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 6ab936bd508cd..007e6d0007869 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: 2024-06-17 +date: 2024-06-18 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 a8e76cbb3f9ae..b287508e816f6 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: 2024-06-17 +date: 2024-06-18 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 0908b45816b60..e60781764e9dd 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: 2024-06-17 +date: 2024-06-18 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 89c43629a3292..0ebdb8b26557d 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: 2024-06-17 +date: 2024-06-18 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 894ac8196e237..4b2a55c6e396c 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: 2024-06-17 +date: 2024-06-18 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 6be3737457dbf..43cfbead9833d 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: 2024-06-17 +date: 2024-06-18 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_security_browser.mdx b/api_docs/kbn_core_security_browser.mdx index 5217068338425..5be1e78d5da9d 100644 --- a/api_docs/kbn_core_security_browser.mdx +++ b/api_docs/kbn_core_security_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser title: "@kbn/core-security-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser'] --- import kbnCoreSecurityBrowserObj from './kbn_core_security_browser.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_internal.mdx b/api_docs/kbn_core_security_browser_internal.mdx index d8714baa91808..991a583cc5e12 100644 --- a/api_docs/kbn_core_security_browser_internal.mdx +++ b/api_docs/kbn_core_security_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-internal title: "@kbn/core-security-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-internal plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-internal'] --- import kbnCoreSecurityBrowserInternalObj from './kbn_core_security_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_mocks.mdx b/api_docs/kbn_core_security_browser_mocks.mdx index 5483add06f3aa..c3c1737fdc9ab 100644 --- a/api_docs/kbn_core_security_browser_mocks.mdx +++ b/api_docs/kbn_core_security_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-mocks title: "@kbn/core-security-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-mocks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-mocks'] --- import kbnCoreSecurityBrowserMocksObj from './kbn_core_security_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_security_common.mdx b/api_docs/kbn_core_security_common.mdx index 3160159c8d12e..9670c5a59d448 100644 --- a/api_docs/kbn_core_security_common.mdx +++ b/api_docs/kbn_core_security_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-common title: "@kbn/core-security-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-common'] --- import kbnCoreSecurityCommonObj from './kbn_core_security_common.devdocs.json'; diff --git a/api_docs/kbn_core_security_server.mdx b/api_docs/kbn_core_security_server.mdx index 84c08982385c4..35be18d36b158 100644 --- a/api_docs/kbn_core_security_server.mdx +++ b/api_docs/kbn_core_security_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server title: "@kbn/core-security-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server'] --- import kbnCoreSecurityServerObj from './kbn_core_security_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_internal.mdx b/api_docs/kbn_core_security_server_internal.mdx index e107bb2d34ed8..3b0ec3fe78699 100644 --- a/api_docs/kbn_core_security_server_internal.mdx +++ b/api_docs/kbn_core_security_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-internal title: "@kbn/core-security-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-internal plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-internal'] --- import kbnCoreSecurityServerInternalObj from './kbn_core_security_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_mocks.mdx b/api_docs/kbn_core_security_server_mocks.mdx index d086b678038a0..ac515de31e89e 100644 --- a/api_docs/kbn_core_security_server_mocks.mdx +++ b/api_docs/kbn_core_security_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-mocks title: "@kbn/core-security-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-mocks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-mocks'] --- import kbnCoreSecurityServerMocksObj from './kbn_core_security_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 39567b1b1bd64..dc33a315941e4 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: 2024-06-17 +date: 2024-06-18 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 d5bde0a90cbd5..b843121cbd69a 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: 2024-06-17 +date: 2024-06-18 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 644cf7f96a29f..ed4b208f4a796 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: 2024-06-17 +date: 2024-06-18 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 3774ed1d3e233..71ea68f7d5ba9 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: 2024-06-17 +date: 2024-06-18 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 7ddefdf2c43c0..cc69f9a7c8175 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: 2024-06-17 +date: 2024-06-18 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 d9dc4054aabef..0b27924382ad5 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: 2024-06-17 +date: 2024-06-18 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 ac9e10ddf7292..f937cd2d8a0a8 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: 2024-06-17 +date: 2024-06-18 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 4aebf41ce691c..ac242965cda10 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: 2024-06-17 +date: 2024-06-18 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_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index e74db79812b59..7a5d6babab383 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.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 ac918665f42ac..bc9bd5e604519 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: 2024-06-17 +date: 2024-06-18 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 7172faff3f4bc..e21547444a200 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: 2024-06-17 +date: 2024-06-18 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 3f8e46e816bf5..1c73e73b8e24d 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: 2024-06-17 +date: 2024-06-18 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_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 3a43a7c1f9a7f..9762a0bf00d2f 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: 2024-06-17 +date: 2024-06-18 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 35bea4f0951ca..6fc4bbaceccfa 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: 2024-06-17 +date: 2024-06-18 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 4a57fb3b80325..098a43228e211 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: 2024-06-17 +date: 2024-06-18 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 b6cce92505cb9..a678369d6eb6c 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: 2024-06-17 +date: 2024-06-18 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 aa5258399d4de..50f6a33ada34e 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: 2024-06-17 +date: 2024-06-18 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 12af0f5b7e589..ae5457505b377 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: 2024-06-17 +date: 2024-06-18 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 5c63ba00710a4..dda6040547258 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: 2024-06-17 +date: 2024-06-18 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 07f69e99e154f..50bc027717952 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: 2024-06-17 +date: 2024-06-18 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 73857d7c42f59..9f5d7558f0cde 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: 2024-06-17 +date: 2024-06-18 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 a3d229869e442..44e691739a9a4 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: 2024-06-17 +date: 2024-06-18 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 d1ecca5536282..b5853c26912dd 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: 2024-06-17 +date: 2024-06-18 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_core_user_profile_browser.mdx b/api_docs/kbn_core_user_profile_browser.mdx index 56eac696e81a3..3f847bb3cbb7b 100644 --- a/api_docs/kbn_core_user_profile_browser.mdx +++ b/api_docs/kbn_core_user_profile_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser title: "@kbn/core-user-profile-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser'] --- import kbnCoreUserProfileBrowserObj from './kbn_core_user_profile_browser.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_internal.mdx b/api_docs/kbn_core_user_profile_browser_internal.mdx index f3bc401c4d717..bbcb96fe8d840 100644 --- a/api_docs/kbn_core_user_profile_browser_internal.mdx +++ b/api_docs/kbn_core_user_profile_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-internal title: "@kbn/core-user-profile-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-internal plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-internal'] --- import kbnCoreUserProfileBrowserInternalObj from './kbn_core_user_profile_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_mocks.mdx b/api_docs/kbn_core_user_profile_browser_mocks.mdx index dae1988c059e9..c95de8602f92e 100644 --- a/api_docs/kbn_core_user_profile_browser_mocks.mdx +++ b/api_docs/kbn_core_user_profile_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-mocks title: "@kbn/core-user-profile-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-mocks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-mocks'] --- import kbnCoreUserProfileBrowserMocksObj from './kbn_core_user_profile_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_common.mdx b/api_docs/kbn_core_user_profile_common.mdx index 857870c56a06e..e76fb89ad8be0 100644 --- a/api_docs/kbn_core_user_profile_common.mdx +++ b/api_docs/kbn_core_user_profile_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-common title: "@kbn/core-user-profile-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-common'] --- import kbnCoreUserProfileCommonObj from './kbn_core_user_profile_common.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server.mdx b/api_docs/kbn_core_user_profile_server.mdx index 152119caae184..ef92831535c47 100644 --- a/api_docs/kbn_core_user_profile_server.mdx +++ b/api_docs/kbn_core_user_profile_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server title: "@kbn/core-user-profile-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server'] --- import kbnCoreUserProfileServerObj from './kbn_core_user_profile_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_internal.mdx b/api_docs/kbn_core_user_profile_server_internal.mdx index 9b04678da2d5d..422f1ce5a92bb 100644 --- a/api_docs/kbn_core_user_profile_server_internal.mdx +++ b/api_docs/kbn_core_user_profile_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-internal title: "@kbn/core-user-profile-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-internal plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-internal'] --- import kbnCoreUserProfileServerInternalObj from './kbn_core_user_profile_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_mocks.mdx b/api_docs/kbn_core_user_profile_server_mocks.mdx index 50c2b3f82f8eb..6e82292c8f67a 100644 --- a/api_docs/kbn_core_user_profile_server_mocks.mdx +++ b/api_docs/kbn_core_user_profile_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-mocks title: "@kbn/core-user-profile-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-mocks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-mocks'] --- import kbnCoreUserProfileServerMocksObj from './kbn_core_user_profile_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 865370737cbaf..bb2abf7052d1a 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index 7e6dccebc5564..e0530e82a349c 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index f02b3fb496e02..8d6830288901c 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: 2024-06-17 +date: 2024-06-18 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 d8a7a6ecd269e..34122d21f5558 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index f1832a8e4a3f8..5c9edfafda6dd 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 609a64e4a9969..2a1a10905c5e9 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index f6ffe6dea5543..24d57726f53c4 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_forge.mdx b/api_docs/kbn_data_forge.mdx index c318399e873c8..6c552996443a5 100644 --- a/api_docs/kbn_data_forge.mdx +++ b/api_docs/kbn_data_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-forge title: "@kbn/data-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-forge plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-forge'] --- import kbnDataForgeObj from './kbn_data_forge.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 1b7c35fd2325c..56d6b807dcf96 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_data_stream_adapter.mdx b/api_docs/kbn_data_stream_adapter.mdx index fee26fa0f2e09..d7755afb4bd0c 100644 --- a/api_docs/kbn_data_stream_adapter.mdx +++ b/api_docs/kbn_data_stream_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-stream-adapter title: "@kbn/data-stream-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-stream-adapter plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-stream-adapter'] --- import kbnDataStreamAdapterObj from './kbn_data_stream_adapter.devdocs.json'; diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index c72ac137a4376..3f9cfd3e15bac 100644 --- a/api_docs/kbn_data_view_utils.mdx +++ b/api_docs/kbn_data_view_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-view-utils title: "@kbn/data-view-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-view-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index d320f47f2bd5f..9bb9de5ed5471 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index f436699b2259e..6f5b8882c4f5a 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index ca4ba92762b06..f4757ad7d1876 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_fleet.mdx b/api_docs/kbn_deeplinks_fleet.mdx index 32edbfb233579..96f0c8c0341cb 100644 --- a/api_docs/kbn_deeplinks_fleet.mdx +++ b/api_docs/kbn_deeplinks_fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-fleet title: "@kbn/deeplinks-fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-fleet plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-fleet'] --- import kbnDeeplinksFleetObj from './kbn_deeplinks_fleet.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index 7d93d245922a7..8b229f4cc19f8 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 30f6072ee703a..cc069e178f4bc 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index 6672a659c774b..d824e8064b963 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 9837a90838425..555bbbf62fdc2 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_security.mdx b/api_docs/kbn_deeplinks_security.mdx index b4c29d128b7bc..3a0f870d4b335 100644 --- a/api_docs/kbn_deeplinks_security.mdx +++ b/api_docs/kbn_deeplinks_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-security title: "@kbn/deeplinks-security" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-security plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-security'] --- import kbnDeeplinksSecurityObj from './kbn_deeplinks_security.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_shared.mdx b/api_docs/kbn_deeplinks_shared.mdx index 17fb23756b2e9..f6f6ad56ad946 100644 --- a/api_docs/kbn_deeplinks_shared.mdx +++ b/api_docs/kbn_deeplinks_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-shared title: "@kbn/deeplinks-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-shared plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-shared'] --- import kbnDeeplinksSharedObj from './kbn_deeplinks_shared.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index c85c1c3dbc9d5..e14dddf6997f9 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index fa0d410971f6d..243fd8639335c 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index c40a95f8bb0d8..8c800bbe4517e 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index 5bf4449370595..face43c46780e 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index c708bfe8d087b..1217a0ca13fa9 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: 2024-06-17 +date: 2024-06-18 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 6520201f20bb3..9d914ba9978e5 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: 2024-06-17 +date: 2024-06-18 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 bf577bba438ee..c59ecdf80707b 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: 2024-06-17 +date: 2024-06-18 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 3cb448a38ebfd..4a501d42c4ebd 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 6852b0a1a51c4..ff6d52f0aec76 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index e46fcf304bc83..a0be6948d2da6 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -840,7 +840,7 @@ "label": "fleet", "description": [], "signature": [ - "{ readonly beatsAgentComparison: string; readonly guide: string; readonly fleetServer: string; readonly fleetServerAddFleetServer: string; readonly esSettings: string; readonly settings: string; readonly logstashSettings: string; readonly kafkaSettings: string; readonly settingsFleetServerHostSettings: string; readonly settingsFleetServerProxySettings: string; readonly troubleshooting: string; readonly elasticAgent: string; readonly datastreams: string; readonly datastreamsILM: string; readonly datastreamsNamingScheme: string; readonly datastreamsManualRollover: string; readonly datastreamsTSDS: string; readonly datastreamsTSDSMetrics: string; readonly installElasticAgent: string; readonly installElasticAgentStandalone: string; readonly packageSignatures: string; readonly upgradeElasticAgent: string; readonly learnMoreBlog: string; readonly apiKeysLearnMore: string; readonly onPremRegistry: string; readonly secureLogstash: string; readonly agentPolicy: string; readonly api: string; readonly uninstallAgent: string; readonly installAndUninstallIntegrationAssets: string; readonly elasticAgentInputConfiguration: string; readonly policySecrets: string; readonly remoteESOoutput: string; readonly performancePresets: string; readonly scalingKubernetesResourcesAndLimits: string; readonly roleAndPrivileges: string; readonly proxiesSettings: string; }" + "{ readonly beatsAgentComparison: string; readonly guide: string; readonly fleetServer: string; readonly fleetServerAddFleetServer: string; readonly esSettings: string; readonly settings: string; readonly logstashSettings: string; readonly kafkaSettings: string; readonly settingsFleetServerHostSettings: string; readonly settingsFleetServerProxySettings: string; readonly troubleshooting: string; readonly elasticAgent: string; readonly datastreams: string; readonly datastreamsILM: string; readonly datastreamsNamingScheme: string; readonly datastreamsManualRollover: string; readonly datastreamsTSDS: string; readonly datastreamsTSDSMetrics: string; readonly datastreamsDownsampling: string; readonly installElasticAgent: string; readonly installElasticAgentStandalone: string; readonly packageSignatures: string; readonly upgradeElasticAgent: string; readonly learnMoreBlog: string; readonly apiKeysLearnMore: string; readonly onPremRegistry: string; readonly secureLogstash: string; readonly agentPolicy: string; readonly api: string; readonly uninstallAgent: string; readonly installAndUninstallIntegrationAssets: string; readonly elasticAgentInputConfiguration: string; readonly policySecrets: string; readonly remoteESOoutput: string; readonly performancePresets: string; readonly scalingKubernetesResourcesAndLimits: string; readonly roleAndPrivileges: string; readonly proxiesSettings: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 7b4148825dc72..99b4070129b90 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: 2024-06-17 +date: 2024-06-18 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 1fd1f16843d71..1c009ad6ae1fb 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index bfe12e9b85204..ad520c4d0940d 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index ec03051ac4e03..ef632ce1a693c 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index f607ea1d0be37..6d0bfdecc3214 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: 2024-06-17 +date: 2024-06-18 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_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index a0c780c5650b8..389bd6dfbcb13 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 8d75bbb7811cf..822df19b8e86f 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index 54c80273b8443..9e4c31025175d 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index 25ff41cc02a9f..198cfcc01bac4 100644 --- a/api_docs/kbn_entities_schema.mdx +++ b/api_docs/kbn_entities_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-entities-schema title: "@kbn/entities-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/entities-schema plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/entities-schema'] --- import kbnEntitiesSchemaObj from './kbn_entities_schema.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index ed9ab2f18ade2..34e7553026526 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: 2024-06-17 +date: 2024-06-18 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 f006c212d642f..fcd3764151fb1 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: 2024-06-17 +date: 2024-06-18 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 6fa3326745f80..a3c7ca961734e 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: 2024-06-17 +date: 2024-06-18 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 1176edac178e6..e952e747c1c0d 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: 2024-06-17 +date: 2024-06-18 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 7b7022d76d8ea..f02fa1ee652b9 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: 2024-06-17 +date: 2024-06-18 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 1ae572d5d6043..1ea8516125ece 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_esql_ast.mdx b/api_docs/kbn_esql_ast.mdx index f1946f2103183..df1043fcfa395 100644 --- a/api_docs/kbn_esql_ast.mdx +++ b/api_docs/kbn_esql_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-ast title: "@kbn/esql-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-ast plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 12ee66d88722b..821d90db7c9a3 100644 --- a/api_docs/kbn_esql_utils.mdx +++ b/api_docs/kbn_esql_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-utils title: "@kbn/esql-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-utils'] --- import kbnEsqlUtilsObj from './kbn_esql_utils.devdocs.json'; diff --git a/api_docs/kbn_esql_validation_autocomplete.mdx b/api_docs/kbn_esql_validation_autocomplete.mdx index f05c67a45f383..8cf5a9051dac7 100644 --- a/api_docs/kbn_esql_validation_autocomplete.mdx +++ b/api_docs/kbn_esql_validation_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-validation-autocomplete title: "@kbn/esql-validation-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-validation-autocomplete plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-validation-autocomplete'] --- import kbnEsqlValidationAutocompleteObj from './kbn_esql_validation_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 841b09da57704..195dcc7f252e4 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index bf0774a4b872e..cd2ffd5dc03be 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 8334451525f44..ddf980c788095 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 4ff1ecb122add..0dbb4516f899b 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index cfe2c88beeb8f..607e6e85b5b86 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 898ea10b60d18..5c30aa5758223 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: 2024-06-17 +date: 2024-06-18 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_formatters.mdx b/api_docs/kbn_formatters.mdx index f81e9144143c9..6badbde276ef9 100644 --- a/api_docs/kbn_formatters.mdx +++ b/api_docs/kbn_formatters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-formatters title: "@kbn/formatters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/formatters plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/formatters'] --- import kbnFormattersObj from './kbn_formatters.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 91f11d5537abc..7d14b862832b8 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: 2024-06-17 +date: 2024-06-18 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_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index b05d6f283ebd1..0816a776cc2d8 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 6baa9b9dfe1eb..273f2e8ae9706 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index 683d3c79b9dce..6e04d34d1e580 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index c8a49fdc38491..89d00a9f4726b 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index 3c198bd6da801..c58584592fe2d 100644 --- a/api_docs/kbn_grouping.mdx +++ b/api_docs/kbn_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grouping title: "@kbn/grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grouping plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grouping'] --- import kbnGroupingObj from './kbn_grouping.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index eaa0629e9bc62..f0c50d75baef5 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: 2024-06-17 +date: 2024-06-18 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 1d2f299d4b79c..92086810350ea 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: 2024-06-17 +date: 2024-06-18 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 61a0941c5a570..dc2e61157905c 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: 2024-06-17 +date: 2024-06-18 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 3c5345798c4be..8b15c7a251945 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: 2024-06-17 +date: 2024-06-18 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 1297af5fcf739..2411e3232b526 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: 2024-06-17 +date: 2024-06-18 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 81f2f00848881..df62efebdf048 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: 2024-06-17 +date: 2024-06-18 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 9a818429802c8..00596b5b41162 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: 2024-06-17 +date: 2024-06-18 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 3ece92db0599c..5b9256cbf9013 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: 2024-06-17 +date: 2024-06-18 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 eb37e77be049c..994dc23e2cdee 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_management.mdx b/api_docs/kbn_index_management.mdx index ebd0afbce2dbc..4216389c07d07 100644 --- a/api_docs/kbn_index_management.mdx +++ b/api_docs/kbn_index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management title: "@kbn/index-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management'] --- import kbnIndexManagementObj from './kbn_index_management.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index 04278a9368654..2fd7b7701b5a5 100644 --- a/api_docs/kbn_inference_integration_flyout.mdx +++ b/api_docs/kbn_inference_integration_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference_integration_flyout title: "@kbn/inference_integration_flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference_integration_flyout plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference_integration_flyout'] --- import kbnInferenceIntegrationFlyoutObj from './kbn_inference_integration_flyout.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index df458c4c1210e..a70f1d03f26a1 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 79a9c6d210c07..e17dbf002a965 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: 2024-06-17 +date: 2024-06-18 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 3c4303a5f9a79..09c2f90cf9a64 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_ipynb.mdx b/api_docs/kbn_ipynb.mdx index d51b3917d6d96..613484e3bcc1b 100644 --- a/api_docs/kbn_ipynb.mdx +++ b/api_docs/kbn_ipynb.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ipynb title: "@kbn/ipynb" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ipynb plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 47e552cffa184..c199e942c4736 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: 2024-06-17 +date: 2024-06-18 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 d8802796021ba..2168b89479953 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: 2024-06-17 +date: 2024-06-18 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 8583d1fda3efa..7b38a3b47dbbe 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: 2024-06-17 +date: 2024-06-18 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 13e63c8d66a2f..e069b954427bd 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: 2024-06-17 +date: 2024-06-18 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 f01e4d1748628..a694f2381cdb4 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index 9d7934ba53dc1..654988afdd9ad 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index e89d5d7cc9844..389fc614a9d04 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index ff90fecc0dd79..ac5cc472bd957 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: 2024-06-17 +date: 2024-06-18 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 8178a1391b976..a7c06f39b8891 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_content_badge.mdx b/api_docs/kbn_managed_content_badge.mdx index 57cc3d3649869..c1e7cc6cb2950 100644 --- a/api_docs/kbn_managed_content_badge.mdx +++ b/api_docs/kbn_managed_content_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-content-badge title: "@kbn/managed-content-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-content-badge plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-content-badge'] --- import kbnManagedContentBadgeObj from './kbn_managed_content_badge.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 91a8523bded27..c4805f5d06330 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index dc976309ee1df..fa34a83354fba 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index 6086490757512..a35cbf8d26019 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index da4190ad3046e..be9c1a2e0b319 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index ca15e140f8660..35b8de7da8653 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index d819a114483b4..e32b94df5ef88 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index 8b945e19d2f21..ecade74c4d985 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index eac3b3e3309a7..03952391dbad1 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 401daabd88b3a..9a3bbd297ed9b 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 26fcb53c1748e..8ecac5821b8d7 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index c472d1f1bdb8e..7f77615f09a8f 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 0b792166ad21c..02190e2aac699 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 2e46b1e309c71..dac4c65101db2 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index c843c94b810d6..5d95f72358409 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index 1e586ae70e6dc..be9bcb20e4aca 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 98da1667f83fa..3a2e1d8eb4855 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: 2024-06-17 +date: 2024-06-18 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_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index a61d79d28324a..3b4dc8c8dbe19 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_cancellable_search.mdx b/api_docs/kbn_ml_cancellable_search.mdx index ecc3dad8006ec..7fda32a6202b6 100644 --- a/api_docs/kbn_ml_cancellable_search.mdx +++ b/api_docs/kbn_ml_cancellable_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-cancellable-search title: "@kbn/ml-cancellable-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-cancellable-search plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-cancellable-search'] --- import kbnMlCancellableSearchObj from './kbn_ml_cancellable_search.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index a68a71c184587..bddad4be53cfe 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index c94664fbafc4d..44c318ad0633a 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index fa07ca5a417ee..899f0313c8a10 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index b10d3d0bb4784..e664eaa61d424 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 1a0d4f5d4a624..cebdf85867838 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: 2024-06-17 +date: 2024-06-18 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_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index 6c39004ba3176..f75310c36f61f 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index 1386e21d31145..510e1542d0f11 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index a69b15aa350ac..ec6dec9b9d60c 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index 8999d750385b2..bd53464f3382e 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: 2024-06-17 +date: 2024-06-18 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 8ce60cf630e63..3739aefe3f9d3 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: 2024-06-17 +date: 2024-06-18 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_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index c6d06a9dee3f9..040eecbaf5325 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 246c04e694349..63e5c5d6286ec 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: 2024-06-17 +date: 2024-06-18 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 a9af04a4754f6..3bb1ec9642670 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: 2024-06-17 +date: 2024-06-18 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_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index 92bab8559e488..815921c27fdfd 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 6a9d2d38db29f..8c6dc446dafbd 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: 2024-06-17 +date: 2024-06-18 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_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index 12193ee482a7e..7733cd5ed1572 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index 60ed40886ff08..008b2619d5bd9 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index 4734419d552ed..9d976957fa693 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 463203ab23a43..1b45e8ff581a6 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: 2024-06-17 +date: 2024-06-18 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_time_buckets.mdx b/api_docs/kbn_ml_time_buckets.mdx index 35808f41675f5..9bed3e7d98e82 100644 --- a/api_docs/kbn_ml_time_buckets.mdx +++ b/api_docs/kbn_ml_time_buckets.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-time-buckets title: "@kbn/ml-time-buckets" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-time-buckets plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-time-buckets'] --- import kbnMlTimeBucketsObj from './kbn_ml_time_buckets.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index f2a33bf0de233..9f171d79b9144 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 907bc0bd4f38e..11c518e24b374 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index d8ab676dee534..d2cda31264ab9 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index f577f22db4f02..4a35bdacaf30c 100644 --- a/api_docs/kbn_mock_idp_utils.mdx +++ b/api_docs/kbn_mock_idp_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mock-idp-utils title: "@kbn/mock-idp-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mock-idp-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mock-idp-utils'] --- import kbnMockIdpUtilsObj from './kbn_mock_idp_utils.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index c987583cd4216..3c3e4138c779f 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 3b8dc07950acd..9992ebe20caaa 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index 930f5e7a79d5c..1dc5321bcf697 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 26d0629c30563..f6153a9f6c1f9 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 046c132f8d36b..7f3e670bbeea4 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index ca2efb80448eb..88d28ea4a83c0 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 04804a93f6d14..418286506e3b3 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 46f985c62a3a7..c3473550ecdfe 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: 2024-06-17 +date: 2024-06-18 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 60f1a092e2990..c57daa10853f1 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: 2024-06-17 +date: 2024-06-18 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 f43913a1fbb35..6e1598dfce37b 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: 2024-06-17 +date: 2024-06-18 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_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 78af9b7fd0129..509330b3de5dc 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 14f653398b46f..3033ba99f1bf1 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: 2024-06-17 +date: 2024-06-18 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_check.mdx b/api_docs/kbn_plugin_check.mdx index bfba51d448dd5..ea93f44e2c8cf 100644 --- a/api_docs/kbn_plugin_check.mdx +++ b/api_docs/kbn_plugin_check.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-check title: "@kbn/plugin-check" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-check plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-check'] --- import kbnPluginCheckObj from './kbn_plugin_check.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index aded1d2975df3..52b89d3991c20 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: 2024-06-17 +date: 2024-06-18 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 65aae400bcb52..ccfb2e0a5ffe9 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_presentation_containers.mdx b/api_docs/kbn_presentation_containers.mdx index cef167f6bd96a..c5fbf9f7dd1a5 100644 --- a/api_docs/kbn_presentation_containers.mdx +++ b/api_docs/kbn_presentation_containers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-containers title: "@kbn/presentation-containers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-containers plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-containers'] --- import kbnPresentationContainersObj from './kbn_presentation_containers.devdocs.json'; diff --git a/api_docs/kbn_presentation_publishing.mdx b/api_docs/kbn_presentation_publishing.mdx index fac38a2bf3261..57d89d5280500 100644 --- a/api_docs/kbn_presentation_publishing.mdx +++ b/api_docs/kbn_presentation_publishing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-publishing title: "@kbn/presentation-publishing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-publishing plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 8d8f2021a29a3..98d3a52877750 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 7f7798e358187..8422a3507cb45 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 8b3a084c45974..939d4a7780390 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_hooks.mdx b/api_docs/kbn_react_hooks.mdx index 86308b7fb03fc..b523cd4752ee5 100644 --- a/api_docs/kbn_react_hooks.mdx +++ b/api_docs/kbn_react_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-hooks title: "@kbn/react-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-hooks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-hooks'] --- import kbnReactHooksObj from './kbn_react_hooks.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 6d272e28acc6b..3d5d27ff2e549 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index 83fb9ae258f82..f581c1b14ca09 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index dce6bdeda2822..3b2494976f6aa 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index 30ed94af5bdb6..29999416ca2c6 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index 769255847c894..c52481c92a2fa 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index 9dc3b1a44d26e..a0347314f8751 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 0ab37f0d32280..77e725cfae3fa 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: 2024-06-17 +date: 2024-06-18 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 6c25f131a4518..aa0bd6217293f 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: 2024-06-17 +date: 2024-06-18 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 9ee8a9b992cd6..d6a38392579e9 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: 2024-06-17 +date: 2024-06-18 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 3c13cb01ec5d9..f017da06d9281 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 02c8eb873e0c2..14bafe45835dc 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_csv_share_panel.mdx b/api_docs/kbn_reporting_csv_share_panel.mdx index 30cfd9d86286c..037f4030f520a 100644 --- a/api_docs/kbn_reporting_csv_share_panel.mdx +++ b/api_docs/kbn_reporting_csv_share_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-csv-share-panel title: "@kbn/reporting-csv-share-panel" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-csv-share-panel plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-csv-share-panel'] --- import kbnReportingCsvSharePanelObj from './kbn_reporting_csv_share_panel.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index 8a6e194435632..4e6da9fa82d13 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index 6a0532f7631db..954b82beae3f0 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index 4f568d36c7515..946ebba102d94 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index e0048f04e496e..bd28fcbcd60ff 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index da68c401e434a..5a3d3485a84a3 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index 9118276f5d388..21a561c316f91 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index b8419571d4b42..502c9b53594fc 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index 7422229fee6fc..af99797625498 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index 8af5d2474d873..0ed4f1d634e57 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 98d30c0e78bd2..8f3ff9bd87637 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_feature_flag_service.mdx b/api_docs/kbn_response_ops_feature_flag_service.mdx index a97ffa2d7f31c..538573427a564 100644 --- a/api_docs/kbn_response_ops_feature_flag_service.mdx +++ b/api_docs/kbn_response_ops_feature_flag_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-feature-flag-service title: "@kbn/response-ops-feature-flag-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-feature-flag-service plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-feature-flag-service'] --- import kbnResponseOpsFeatureFlagServiceObj from './kbn_response_ops_feature_flag_service.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 32b46c7cfce9b..abf549f7879de 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index 766dbc9de5469..189a616816212 100644 --- a/api_docs/kbn_router_to_openapispec.mdx +++ b/api_docs/kbn_router_to_openapispec.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-to-openapispec title: "@kbn/router-to-openapispec" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-to-openapispec plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-to-openapispec'] --- import kbnRouterToOpenapispecObj from './kbn_router_to_openapispec.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index 4e8dff0fd2163..d2bc968cce112 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index c0678bbb387e7..6753bb86d6d85 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index bf4b1a5e20ff2..7f70d045f06ee 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 2945765803a1e..b68bf847f8b02 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index d43d0f5f7950c..241233903437a 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 632f445a2e4cb..61f576ccec4c4 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index 90ad4394d37ad..c04430411fd4e 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index 1500bfe3ac9ca..ee933ffadffc5 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 308e260525477..a4911af523c9f 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index 8e5c8573924ac..dacc0a63e4c55 100644 --- a/api_docs/kbn_search_types.mdx +++ b/api_docs/kbn_search_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-types title: "@kbn/search-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index 1232bf4143835..c1d99a522e9bc 100644 --- a/api_docs/kbn_security_hardening.mdx +++ b/api_docs/kbn_security_hardening.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-hardening title: "@kbn/security-hardening" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-hardening plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-hardening'] --- import kbnSecurityHardeningObj from './kbn_security_hardening.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index 98c21f7f70ece..78ab45087fb48 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 057fef5e5ef5d..64ee1ad1bd645 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.devdocs.json b/api_docs/kbn_security_plugin_types_server.devdocs.json index 2100c7e7f1beb..15aea85d3b059 100644 --- a/api_docs/kbn_security_plugin_types_server.devdocs.json +++ b/api_docs/kbn_security_plugin_types_server.devdocs.json @@ -3193,83 +3193,83 @@ }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/security.ts" + "path": "x-pack/plugins/fleet/server/services/api_keys/security.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/api_keys/transform_api_keys.ts" + "path": "x-pack/plugins/fleet/server/services/security/security.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/api_keys/security.ts" + "path": "x-pack/plugins/fleet/server/services/api_keys/transform_api_keys.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/setup/fleet_server_policies_enrollment_keys.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/setup/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/services/setup/fleet_server_policies_enrollment_keys.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/setup/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" }, { "plugin": "cloudDefend", diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index c9087ea8023c5..7476a1f55a9f4 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 3a1d5e7369cb2..1ec8908ff8655 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index e841ca2c8f0bd..f3762cab5063e 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index ba1039d1dfd6f..63f4a70fb155c 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index ae4b404ccef50..1d7460b5e9c07 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 10961d6963e23..337f9ac61e761 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 4814ce044f782..7737f3b2578f9 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 428eedbb2e807..0e9c907dcd407 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: 2024-06-17 +date: 2024-06-18 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 c79ea89803b9d..787dc2539f43f 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: 2024-06-17 +date: 2024-06-18 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 aa2e7bccc0247..8693ad038c7fd 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: 2024-06-17 +date: 2024-06-18 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 06c14f87a45ef..da917f28d8f8f 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: 2024-06-17 +date: 2024-06-18 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 daeead88afc6e..a72ea475312b4 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: 2024-06-17 +date: 2024-06-18 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 71b579c0a0d70..07d7b4f7cc05b 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: 2024-06-17 +date: 2024-06-18 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 4fae5675a8945..843e91cd41738 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: 2024-06-17 +date: 2024-06-18 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 fb3633c531750..af215ed77ffa2 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: 2024-06-17 +date: 2024-06-18 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 2d942f0a44056..57d831ae429c5 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: 2024-06-17 +date: 2024-06-18 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 bf16d9874b489..63316808fdde3 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: 2024-06-17 +date: 2024-06-18 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 88975150d101f..28a0375931771 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: 2024-06-17 +date: 2024-06-18 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 f2393772847ad..d5b841b270615 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: 2024-06-17 +date: 2024-06-18 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 36f1312f61b59..f444befb87ea9 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: 2024-06-17 +date: 2024-06-18 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 66b123bb07699..825c6d54bda3c 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: 2024-06-17 +date: 2024-06-18 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 ebda0f1aa6172..59e218ff76cb3 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: 2024-06-17 +date: 2024-06-18 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 b5d552e453360..aa80f0b9ec573 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: 2024-06-17 +date: 2024-06-18 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 9309e3c61b357..811665eb47b51 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index 3635ca2fe050a..c60933aa55a3b 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index 7af28b5703e55..79fd5ca3170ce 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 58f50eb9b4a65..3786cf44243be 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 95b1d08073596..f98f68069a3d1 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 4d68a8e795e2b..9fa1a0a96fc5e 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 22ee70fb1002b..86bb254e27cee 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index c5e0727964851..d055e16990504 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: 2024-06-17 +date: 2024-06-18 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 e6e7eaf2bd78d..f9430a3121623 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: 2024-06-17 +date: 2024-06-18 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_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 3488a9ea6bcb6..479d22cd7919b 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: 2024-06-17 +date: 2024-06-18 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_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 9511099b23487..f2f59187e78bd 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 46591e962fe0c..f7bcd8a674ca2 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: 2024-06-17 +date: 2024-06-18 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 5b2499326c902..c8f79c0b8358e 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: 2024-06-17 +date: 2024-06-18 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_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index c998ff4165ee6..a3f3cb94eb74e 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index 167e09ffee9e1..6927e6aef13c5 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index b7c756a0313e6..b638794940fb2 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: 2024-06-17 +date: 2024-06-18 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 f27479e18f11f..fe51f1707507a 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: 2024-06-17 +date: 2024-06-18 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 b36b15944c3b6..282088305558b 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: 2024-06-17 +date: 2024-06-18 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 391ac024acb87..16d456a7c75b4 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: 2024-06-17 +date: 2024-06-18 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 6c60d31e46ba6..b431671ab16b3 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: 2024-06-17 +date: 2024-06-18 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_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index cc371e6820af4..6c1c20a32139f 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 039adb8ece3ba..5b8d449359e9b 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: 2024-06-17 +date: 2024-06-18 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 61d3c1988aadc..f45045dcaffab 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: 2024-06-17 +date: 2024-06-18 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 0c6b6b8f51194..1f2e3ff7d743a 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: 2024-06-17 +date: 2024-06-18 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 f6d2a25b7a603..ce75751d7cb98 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: 2024-06-17 +date: 2024-06-18 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 f958c0f56a69f..c35451215f230 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: 2024-06-17 +date: 2024-06-18 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.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 2579dadd0415d..cf0a2a23e81ec 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: 2024-06-17 +date: 2024-06-18 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 a1329fa0de838..7d7ecdc6922e8 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: 2024-06-17 +date: 2024-06-18 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 2ecba86c2473c..f772e6004e16d 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: 2024-06-17 +date: 2024-06-18 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 421cf76e284ee..5be2c91a22b83 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: 2024-06-17 +date: 2024-06-18 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 3f64089023a61..887a31b40b280 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: 2024-06-17 +date: 2024-06-18 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 979dbc82c219e..7511487ba56bf 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: 2024-06-17 +date: 2024-06-18 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 a75d6664bc60e..88c3b4d5eb75f 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: 2024-06-17 +date: 2024-06-18 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 3f20ea7801109..0ce60fec248f9 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: 2024-06-17 +date: 2024-06-18 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 df30092cd1a33..831e5bdba8652 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: 2024-06-17 +date: 2024-06-18 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 e2d39ccd79c50..7740c3e4c160c 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: 2024-06-17 +date: 2024-06-18 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 729864ab7ab7f..13423d36e33c6 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: 2024-06-17 +date: 2024-06-18 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 52ab086a5f40f..be82ba5e352dd 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: 2024-06-17 +date: 2024-06-18 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 248c645716584..a7bb6856b2dc5 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: 2024-06-17 +date: 2024-06-18 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 a4454b8ed220d..6fc5f819983cf 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: 2024-06-17 +date: 2024-06-18 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 d1f2c0fe743e9..e53ad09f41e05 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: 2024-06-17 +date: 2024-06-18 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 5e1d0141386a4..6144fc2b154d3 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: 2024-06-17 +date: 2024-06-18 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 f96409b7154f1..638e6c72f0cea 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: 2024-06-17 +date: 2024-06-18 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 52c275264fe93..69068b73c4fb5 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: 2024-06-17 +date: 2024-06-18 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 2a4c3c6400fe2..d2ece90392a85 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: 2024-06-17 +date: 2024-06-18 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_tabbed_modal.mdx b/api_docs/kbn_shared_ux_tabbed_modal.mdx index 7c34954ad71ea..7d52676fbebc4 100644 --- a/api_docs/kbn_shared_ux_tabbed_modal.mdx +++ b/api_docs/kbn_shared_ux_tabbed_modal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-tabbed-modal title: "@kbn/shared-ux-tabbed-modal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-tabbed-modal plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-tabbed-modal'] --- import kbnSharedUxTabbedModalObj from './kbn_shared_ux_tabbed_modal.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 6abe34b608bbe..23ce9cf96a2a8 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: 2024-06-17 +date: 2024-06-18 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.devdocs.json b/api_docs/kbn_slo_schema.devdocs.json index 8acc3fb8c8aac..5707fe5fd6e53 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -760,7 +760,7 @@ "label": "FetchHistoricalSummaryResponse", "description": [], "signature": [ - "{ sloId: string; instanceId: string; data: ({ date: string; } & { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; } & { summaryUpdatedAt?: string | null | undefined; })[]; }[]" + "{ sloId: string; instanceId: string; data: { date: string; status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }[]; }[]" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts", "deprecated": false, @@ -880,7 +880,7 @@ "label": "FindSLOParams", "description": [], "signature": [ - "{ filters?: string | undefined; kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; hideStale?: boolean | undefined; }" + "{ filters?: string | undefined; kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | \"burn_rate_5m\" | \"burn_rate_1h\" | \"burn_rate_1d\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; hideStale?: boolean | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find.ts", "deprecated": false, @@ -895,7 +895,7 @@ "label": "FindSLOResponse", "description": [], "signature": [ - "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; })[]; }" + "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; })[]; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find.ts", "deprecated": false, @@ -993,7 +993,7 @@ "label": "GetSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get.ts", "deprecated": false, @@ -1083,7 +1083,7 @@ "label": "HistoricalSummaryResponse", "description": [], "signature": [ - "{ date: string; } & { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; } & { summaryUpdatedAt?: string | null | undefined; }" + "{ date: string; status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts", "deprecated": false, @@ -1293,7 +1293,7 @@ "label": "SLOWithSummaryResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; dataViewId?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; settings: { syncDelay: string; frequency: string; preventInitialBackfill: boolean; }; revision: number; enabled: boolean; tags: string[]; createdAt: string; updatedAt: string; groupBy: string | string[]; version: number; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; fiveMinuteBurnRate: number; oneHourBurnRate: number; oneDayBurnRate: number; } & { summaryUpdatedAt?: string | null | undefined; }; groupings: { [x: string]: string | number; }; } & { instanceId?: string | undefined; meta?: { synthetics?: { monitorId: string; locationId: string; configId: string; } | undefined; } | undefined; remote?: { remoteName: string; kibanaUrl: string; } | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -3563,16 +3563,10 @@ "]>; data: ", "ArrayC", "<", - "IntersectionC", - "<[", "TypeC", "<{ date: ", "Type", - "; }>, ", - "IntersectionC", - "<[", - "TypeC", - "<{ status: ", + "; status: ", "UnionC", "<[", "LiteralC", @@ -3594,15 +3588,7 @@ "NumberC", "; isEstimated: ", "BooleanC", - "; }>; }>, ", - "PartialC", - "<{ summaryUpdatedAt: ", - "UnionC", - "<[", - "StringC", - ", ", - "NullC", - "]>; }>]>]>>; }>>" + "; }>; }>>; }>>" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts", "deprecated": false, @@ -5384,7 +5370,13 @@ "LiteralC", "<\"sli_value\">, ", "LiteralC", - "<\"status\">]>; sortDirection: ", + "<\"status\">, ", + "LiteralC", + "<\"burn_rate_5m\">, ", + "LiteralC", + "<\"burn_rate_1h\">, ", + "LiteralC", + "<\"burn_rate_1d\">]>; sortDirection: ", "UnionC", "<[", "LiteralC", @@ -6888,7 +6880,13 @@ "NumberC", "; isEstimated: ", "BooleanC", - "; }>; }>, ", + "; }>; fiveMinuteBurnRate: ", + "NumberC", + "; oneHourBurnRate: ", + "NumberC", + "; oneDayBurnRate: ", + "NumberC", + "; }>, ", "PartialC", "<{ summaryUpdatedAt: ", "UnionC", @@ -9998,7 +9996,13 @@ "NumberC", "; isEstimated: ", "BooleanC", - "; }>; }>, ", + "; }>; fiveMinuteBurnRate: ", + "NumberC", + "; oneHourBurnRate: ", + "NumberC", + "; oneDayBurnRate: ", + "NumberC", + "; }>, ", "PartialC", "<{ summaryUpdatedAt: ", "UnionC", @@ -10531,16 +10535,10 @@ "label": "historicalSummarySchema", "description": [], "signature": [ - "IntersectionC", - "<[", "TypeC", "<{ date: ", "Type", - "; }>, ", - "IntersectionC", - "<[", - "TypeC", - "<{ status: ", + "; status: ", "UnionC", "<[", "LiteralC", @@ -10562,15 +10560,7 @@ "NumberC", "; isEstimated: ", "BooleanC", - "; }>; }>, ", - "PartialC", - "<{ summaryUpdatedAt: ", - "UnionC", - "<[", - "StringC", - ", ", - "NullC", - "]>; }>]>]>" + "; }>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts", "deprecated": false, @@ -17608,7 +17598,13 @@ "NumberC", "; isEstimated: ", "BooleanC", - "; }>; }>, ", + "; }>; fiveMinuteBurnRate: ", + "NumberC", + "; oneHourBurnRate: ", + "NumberC", + "; oneDayBurnRate: ", + "NumberC", + "; }>, ", "PartialC", "<{ summaryUpdatedAt: ", "UnionC", @@ -17738,7 +17734,13 @@ "NumberC", "; isEstimated: ", "BooleanC", - "; }>; }>, ", + "; }>; fiveMinuteBurnRate: ", + "NumberC", + "; oneHourBurnRate: ", + "NumberC", + "; oneDayBurnRate: ", + "NumberC", + "; }>, ", "PartialC", "<{ summaryUpdatedAt: ", "UnionC", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 01cd0aa5c092b..3a7ba2b4f2f63 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: 2024-06-17 +date: 2024-06-18 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 cf7dd2955ee5c..14d5c70653e93 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_predicates.mdx b/api_docs/kbn_sort_predicates.mdx index 9f7e481a4e92f..2011280cc0505 100644 --- a/api_docs/kbn_sort_predicates.mdx +++ b/api_docs/kbn_sort_predicates.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-predicates title: "@kbn/sort-predicates" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-predicates plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index c1e25e156c40c..3cdbb6cb2c659 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: 2024-06-17 +date: 2024-06-18 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 c375dc911e6ad..9252cdc7046f5 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: 2024-06-17 +date: 2024-06-18 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 0b3d79c530c5e..cd1c35ec26988 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: 2024-06-17 +date: 2024-06-18 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 6ddba8dc26974..d3d2817392972 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.devdocs.json b/api_docs/kbn_test.devdocs.json index 7f24cc4e8ca6f..d3b0fa6729cbf 100644 --- a/api_docs/kbn_test.devdocs.json +++ b/api_docs/kbn_test.devdocs.json @@ -1782,6 +1782,38 @@ ], "returnComment": [] }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.SamlSessionManager.getEmail", + "type": "Function", + "tags": [], + "label": "getEmail", + "description": [], + "signature": [ + "(role: string) => Promise" + ], + "path": "packages/kbn-test/src/auth/session_manager.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/test", + "id": "def-common.SamlSessionManager.getEmail.$1", + "type": "string", + "tags": [], + "label": "role", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-test/src/auth/session_manager.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "@kbn/test", "id": "def-common.SamlSessionManager.getUserData", @@ -1790,7 +1822,9 @@ "label": "getUserData", "description": [], "signature": [ - "(role: string) => Promise<{ email: string; fullname: string; }>" + "(role: string) => Promise<", + "UserProfile", + ">" ], "path": "packages/kbn-test/src/auth/session_manager.ts", "deprecated": false, diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index c37657a4c6b4f..4421b40340122 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 313 | 4 | 265 | 12 | +| 315 | 4 | 267 | 13 | ## Common diff --git a/api_docs/kbn_test_eui_helpers.mdx b/api_docs/kbn_test_eui_helpers.mdx index ff3549b2dbfa7..1788f6e0829da 100644 --- a/api_docs/kbn_test_eui_helpers.mdx +++ b/api_docs/kbn_test_eui_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-eui-helpers title: "@kbn/test-eui-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-eui-helpers plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-eui-helpers'] --- import kbnTestEuiHelpersObj from './kbn_test_eui_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 4e448d4eb1a64..16fb734220c89 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: 2024-06-17 +date: 2024-06-18 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 571fa45648a6a..38d549f82a90d 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index a89e7fa45f8b4..75e745709a74f 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index 461b70833eef4..2d097d5e75e74 100644 --- a/api_docs/kbn_timerange.mdx +++ b/api_docs/kbn_timerange.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-timerange title: "@kbn/timerange" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/timerange plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/timerange'] --- import kbnTimerangeObj from './kbn_timerange.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 3ebf1520252bb..9e716aecc945c 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 78669fbf897c6..5bdef7f4e25c6 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_try_in_console.mdx b/api_docs/kbn_try_in_console.mdx index b49e4cd037a87..3c3e9e346edad 100644 --- a/api_docs/kbn_try_in_console.mdx +++ b/api_docs/kbn_try_in_console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-try-in-console title: "@kbn/try-in-console" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/try-in-console plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/try-in-console'] --- import kbnTryInConsoleObj from './kbn_try_in_console.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 9efd9400402da..db8ccb63f12c8 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: 2024-06-17 +date: 2024-06-18 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 fb9ad77c72eff..8428e9a42bbd7 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: 2024-06-17 +date: 2024-06-18 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 8addb8d57ed80..4acf3eb5e68ba 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: 2024-06-17 +date: 2024-06-18 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 babfa755367fc..45443736b64cf 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: 2024-06-17 +date: 2024-06-18 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 cfe2d5adb12f6..11c3a78190214 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index b25351326f188..6470406f9b3cb 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index e0d919234d3a6..0e904c901ade3 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 35516a91b7ec0..0b3533175afd7 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index 3cde751797a54..3529addc44268 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_prompt.mdx b/api_docs/kbn_unsaved_changes_prompt.mdx index 566058b20edcd..6877c9595ecd2 100644 --- a/api_docs/kbn_unsaved_changes_prompt.mdx +++ b/api_docs/kbn_unsaved_changes_prompt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-prompt title: "@kbn/unsaved-changes-prompt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-prompt plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-prompt'] --- import kbnUnsavedChangesPromptObj from './kbn_unsaved_changes_prompt.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 3e3adc7521fb9..7aa3a96e56451 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 77b41c7eed6ab..5149cf98e47f9 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: 2024-06-17 +date: 2024-06-18 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 d7b59ac3f14ea..5fe09a5bb7435 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: 2024-06-17 +date: 2024-06-18 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 a5081ef999d42..d02ac34ef384f 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: 2024-06-17 +date: 2024-06-18 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 3f2a12356443f..3ad836e69f7ad 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 6a624e6e06f1c..7a12739a8a49b 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index 6e91f481911fe..7adc25184d8eb 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 79644c810c284..76384b88894ad 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 63153d9efd0da..3912fb378253c 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index 772acffc1bd28..21ca40473b28e 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 0d662c99e6770..68e7dc0095685 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: 2024-06-17 +date: 2024-06-18 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 ba8d0979b80a5..a771d0a42ff2f 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: 2024-06-17 +date: 2024-06-18 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 0d0a98f5a8ff3..a7ed980f094eb 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: 2024-06-17 +date: 2024-06-18 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 c9ab77fb77b31..307f3dc924d14 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: 2024-06-17 +date: 2024-06-18 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 82ca8dad4c608..8d5aa484a4f29 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: 2024-06-17 +date: 2024-06-18 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 e146a2fc37e13..91f753208affb 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: 2024-06-17 +date: 2024-06-18 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 1297b5e11f2e4..3553269ec96e9 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 7b4f39b14b024..05a287f91b129 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 2584222ce481d..5dbd8b3e558aa 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 418e51c4a6f1d..ab66bbd113633 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 588514ebf3ef4..6f9539d43aac2 100644 --- a/api_docs/logs_data_access.mdx +++ b/api_docs/logs_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsDataAccess title: "logsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the logsDataAccess plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsDataAccess'] --- import logsDataAccessObj from './logs_data_access.devdocs.json'; diff --git a/api_docs/logs_explorer.mdx b/api_docs/logs_explorer.mdx index f631d3ee2e99b..80e08ec4cf6f7 100644 --- a/api_docs/logs_explorer.mdx +++ b/api_docs/logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsExplorer title: "logsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logsExplorer plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsExplorer'] --- import logsExplorerObj from './logs_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 68cbc3e157e0a..3f2e723b5579a 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 2fc02980dd101..ed2c0c3d95e7b 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: 2024-06-17 +date: 2024-06-18 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 acd7a2070f619..d6f7a1d8cce9a 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: 2024-06-17 +date: 2024-06-18 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 99a119682fa7e..11fbb4d97f7e7 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 8f48d1167fbbd..c1e9164d20921 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 95a0187a6ad75..3d83b78e1cf32 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index 7832f4f2bf928..0d1627d4941c8 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index d51708b8f602f..06c2e7e11e522 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: 2024-06-17 +date: 2024-06-18 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 d58b02a3c4b85..3f382a0a6f1a3 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: 2024-06-17 +date: 2024-06-18 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 5063e89578106..4fc030a3e7712 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: 2024-06-17 +date: 2024-06-18 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 05b055cb03bcb..056c9b626c0ac 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index 5a4e745dadc11..68e23117c862a 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index df9e71af6dee5..acdbb39c7900e 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: 2024-06-17 +date: 2024-06-18 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 1a318291fa2a6..eb76936ebe69d 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 16b571077703c..62922ef331bbf 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index ef4215909beb9..2d72d3c575926 100644 --- a/api_docs/observability_a_i_assistant_app.mdx +++ b/api_docs/observability_a_i_assistant_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistantApp title: "observabilityAIAssistantApp" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistantApp plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistantApp'] --- import observabilityAIAssistantAppObj from './observability_a_i_assistant_app.devdocs.json'; diff --git a/api_docs/observability_ai_assistant_management.mdx b/api_docs/observability_ai_assistant_management.mdx index 367e7aaef7d8f..368830b966205 100644 --- a/api_docs/observability_ai_assistant_management.mdx +++ b/api_docs/observability_ai_assistant_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAiAssistantManagement title: "observabilityAiAssistantManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAiAssistantManagement plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAiAssistantManagement'] --- import observabilityAiAssistantManagementObj from './observability_ai_assistant_management.devdocs.json'; diff --git a/api_docs/observability_logs_explorer.mdx b/api_docs/observability_logs_explorer.mdx index 190c448c2aa95..509dc56ef16b8 100644 --- a/api_docs/observability_logs_explorer.mdx +++ b/api_docs/observability_logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogsExplorer title: "observabilityLogsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogsExplorer plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogsExplorer'] --- import observabilityLogsExplorerObj from './observability_logs_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index 2e8d03245163e..47b27382ed39f 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index 9cca2ad645a00..9a7f818c21a99 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index d5eec5505e934..2656666b957d7 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index 2396233c26969..31904a5a9443e 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 4dfdaac6b4daf..13c56f83dab90 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 49116 | 239 | 37582 | 1873 | +| 49119 | 239 | 37584 | 1875 | ## Plugin Directory @@ -101,7 +101,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 84 | 0 | 84 | 8 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 240 | 0 | 24 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 0 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1337 | 5 | 1216 | 71 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1338 | 5 | 1216 | 72 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 72 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -717,7 +717,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 4 | 0 | 2 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 41 | 2 | 21 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 5 | 1 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 313 | 4 | 265 | 12 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 315 | 4 | 267 | 13 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 25 | 0 | 13 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 131 | 3 | 98 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 1 | 0 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index aa3f68aff7703..55e27dddad02f 100644 --- a/api_docs/presentation_panel.mdx +++ b/api_docs/presentation_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationPanel title: "presentationPanel" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationPanel plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 91cb071ee35f8..0cbb54c1599bc 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 761810531e4ae..59843ba7bdd49 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index 9947501c2f541..5c2ba575a0824 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 63ed8a745eb51..5dd63fc0897b0 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: 2024-06-17 +date: 2024-06-18 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 8e7bde64480b3..006a1a383fb19 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: 2024-06-17 +date: 2024-06-18 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 7647262c33927..e82d752c9c713 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: 2024-06-17 +date: 2024-06-18 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 f2082ab5c6618..982b4f418e67b 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: 2024-06-17 +date: 2024-06-18 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 c2c281d589b17..cacdcf0747d1f 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: 2024-06-17 +date: 2024-06-18 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 2396e3cf84792..5fb36ebc0642e 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: 2024-06-17 +date: 2024-06-18 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 9bacb651df27b..df8d813489241 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index ddc363e901346..71d04fa6f6d06 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: 2024-06-17 +date: 2024-06-18 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 320061330ee65..0f855887386a8 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: 2024-06-17 +date: 2024-06-18 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 474abc799ddab..0e2007a50b871 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: 2024-06-17 +date: 2024-06-18 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 5ece66b9e095e..c65779a953eb0 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: 2024-06-17 +date: 2024-06-18 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 6dfc43ab84a75..6061c6ce60372 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: 2024-06-17 +date: 2024-06-18 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 ad19664649f12..41de4c90572e6 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index d982c87ac9811..e27f2058a1a4d 100644 --- a/api_docs/search_connectors.mdx +++ b/api_docs/search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchConnectors title: "searchConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the searchConnectors plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index a5f6b6a6f5529..7c617046a080e 100644 --- a/api_docs/search_inference_endpoints.mdx +++ b/api_docs/search_inference_endpoints.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchInferenceEndpoints title: "searchInferenceEndpoints" image: https://source.unsplash.com/400x175/?github description: API docs for the searchInferenceEndpoints plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index 3ff93cc375d3a..efc97cf266849 100644 --- a/api_docs/search_notebooks.mdx +++ b/api_docs/search_notebooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNotebooks title: "searchNotebooks" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNotebooks plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNotebooks'] --- import searchNotebooksObj from './search_notebooks.devdocs.json'; diff --git a/api_docs/search_playground.mdx b/api_docs/search_playground.mdx index 3bb2207551def..fd6257e783ef7 100644 --- a/api_docs/search_playground.mdx +++ b/api_docs/search_playground.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchPlayground title: "searchPlayground" image: https://source.unsplash.com/400x175/?github description: API docs for the searchPlayground plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/security.devdocs.json b/api_docs/security.devdocs.json index eddfbc9e2951a..f43fe4bd96a09 100644 --- a/api_docs/security.devdocs.json +++ b/api_docs/security.devdocs.json @@ -5497,83 +5497,83 @@ }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/security.ts" + "path": "x-pack/plugins/fleet/server/services/api_keys/security.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/api_keys/transform_api_keys.ts" + "path": "x-pack/plugins/fleet/server/services/security/security.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/api_keys/security.ts" + "path": "x-pack/plugins/fleet/server/services/api_keys/transform_api_keys.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/setup/fleet_server_policies_enrollment_keys.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/setup/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/package_policy/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/services/setup/fleet_server_policies_enrollment_keys.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/setup/handlers.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts" + "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" }, { "plugin": "cloudDefend", diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 7f48fc8e0146e..d1327bb9f85f5 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: 2024-06-17 +date: 2024-06-18 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 ff4abc085b228..09fd66a8fa53b 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index e0aa8b4333f06..da3e0b614f45b 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index 2463a21b9e4df..4dfe48856ba18 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 706096cf75fd3..2b167cbb92301 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index fbf138978c19f..0a361ed9f29d4 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index 158be33f61896..e48d941822de4 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 2e0eaec6c1144..dc8c512217b73 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: 2024-06-17 +date: 2024-06-18 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 63f66580020cc..65f4bf5340d47 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index 6fd44e6aabc8e..4615111556016 100644 --- a/api_docs/slo.mdx +++ b/api_docs/slo.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/slo title: "slo" image: https://source.unsplash.com/400x175/?github description: API docs for the slo plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'slo'] --- import sloObj from './slo.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index b6828d11044bc..895059ad9b055 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: 2024-06-17 +date: 2024-06-18 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 81284051cb42c..e9f21582eff65 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: 2024-06-17 +date: 2024-06-18 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 bb9a6d60814ec..3737d2302fe6b 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: 2024-06-17 +date: 2024-06-18 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 4e717680a744f..6b67580e44db9 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: 2024-06-17 +date: 2024-06-18 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 582c46c324603..f49b7846ed095 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: 2024-06-17 +date: 2024-06-18 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 8b3662d241228..178ea146c56ba 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: 2024-06-17 +date: 2024-06-18 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 183abe90f1e60..2a237ce79ed09 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: 2024-06-17 +date: 2024-06-18 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 97a61b6b9a25e..c35b4097e77e8 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: 2024-06-17 +date: 2024-06-18 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 0e4e3e8dbf435..444de09aa6b4a 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index 1e6081c3edbb0..2b06f627d6f2d 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index fc7f6e67de76c..5b74a01369404 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: 2024-06-17 +date: 2024-06-18 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 7e5416c976f5f..bcb9dba7866d9 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: 2024-06-17 +date: 2024-06-18 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 72bffa7500a42..76563f3a7636a 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: 2024-06-17 +date: 2024-06-18 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 727a49320f781..a82268cb54719 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: 2024-06-17 +date: 2024-06-18 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 4ed721b537c36..dc674fa70fdf7 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: 2024-06-17 +date: 2024-06-18 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 78c09c4820ac9..953b01ceadd39 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index e0af6eb5c893c..d738743a9477e 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 264716778d31f..2454d26694b22 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: 2024-06-17 +date: 2024-06-18 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 813ec045cd9de..6ddb906f1436a 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: 2024-06-17 +date: 2024-06-18 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 533fea4599ee8..7d9046ef2e02b 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index 77b17b0d50d2c..35f9262187c03 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 819922fd4335f..d15b383e344da 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: 2024-06-17 +date: 2024-06-18 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 d3e7e16b9f13b..8d1371644bd4d 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: 2024-06-17 +date: 2024-06-18 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 19c252a88673f..aa257292348cd 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: 2024-06-17 +date: 2024-06-18 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 8ff7f742ac410..4c024378c51a5 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: 2024-06-17 +date: 2024-06-18 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 5d859c8a16fdf..984c102379604 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: 2024-06-17 +date: 2024-06-18 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 44bdad781d962..de21d886b7c46 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: 2024-06-17 +date: 2024-06-18 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 3abc3594f7fff..ee4144f629efe 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: 2024-06-17 +date: 2024-06-18 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 64c76b9c5ee86..0cd0162750577 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: 2024-06-17 +date: 2024-06-18 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 2c126e0d7461a..59414d94e8ed8 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: 2024-06-17 +date: 2024-06-18 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 f2b754d3f633a..d9f9590acbe69 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: 2024-06-17 +date: 2024-06-18 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 e0dff8da03753..30af10196561f 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: 2024-06-17 +date: 2024-06-18 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 c4c16340f64c2..5c5f8367dc6b9 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: 2024-06-17 +date: 2024-06-18 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 4499a267601de..0ca9f2fe7118c 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: 2024-06-17 +date: 2024-06-18 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 a268fa4c22655..1176ba240c38e 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: 2024-06-17 +date: 2024-06-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From ef91afd9c1c31f6700e02af79b3f610ace4b109c Mon Sep 17 00:00:00 2001 From: Agustina Nahir Ruidiaz <61565784+agusruidiazgd@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:49:27 +0200 Subject: [PATCH 029/127] issue-177204: show username when fullName is empty string (#186298) ## Summary We could find and edge case on ESS Custom User doing QA on the issue: https://github.com/elastic/kibana/issues/177204. When user's full name is an empty string (not undefined or null) the greeting message was not displaying. In this PR, we change the logic and display user's username whenever the user's fullName value is an empty string. Before: ![image](https://github.com/elastic/kibana/assets/61565784/9138a923-647c-4c6d-9300-340040545e55) How it looks now: ![image](https://github.com/elastic/kibana/assets/61565784/d451ed60-cdcf-41f1-a01a-12f5d0c4202a) ### **Checklist** - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios. --- .../onboarding/welcome_header/index.test.tsx | 10 ++++++++++ .../landing_page/onboarding/welcome_header/index.tsx | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx index 0eaf44e9cc69c..8939ffd1456cd 100644 --- a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx @@ -42,6 +42,16 @@ describe('WelcomeHeaderComponent', () => { expect(titleElement).toBeInTheDocument(); }); + it('should render username when fullName is an empty string', () => { + const fullName = ''; + const username = 'jd'; + mockUseCurrentUser.mockReturnValue({ fullName, username }); + + const { getByText } = render(); + const titleElement = getByText(`Hi ${username}!`); + expect(titleElement).toBeInTheDocument(); + }); + it('should render username when fullName is not provided', () => { const username = 'jd'; mockUseCurrentUser.mockReturnValue({ username }); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx index 848eece5b243a..f659f8a0a4599 100644 --- a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx @@ -24,7 +24,7 @@ const WelcomeHeaderComponent: React.FC<{ productTier?: ProductTier }> = ({ produ const userName = useCurrentUser(); // Full name could be null, user name should always exist - const name = userName?.fullName ?? userName?.username; + const name = userName?.fullName || userName?.username; const projectFeaturesUrl = useProjectFeaturesUrl(); From 8ad77f6df9cc29b2218ded53209f9e97c595d0ff Mon Sep 17 00:00:00 2001 From: Antonio Date: Tue, 18 Jun 2024 09:03:00 +0200 Subject: [PATCH 030/127] [ResponseOps][Cases] Fix `edit tags` flaky test (#186295) Fixes [#175655](https://github.com/elastic/kibana/issues/175655) ## Summary The other tests already tested the edit button so I changed the scope to look only for the `no tags` message. --- .../case_view/components/edit_tags.test.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx index 7ced679368434..583d7599d14cb 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx @@ -25,8 +25,7 @@ const defaultProps: EditTagsProps = { tags: [], }; -// FLAKY: https://github.com/elastic/kibana/issues/175655 -describe.skip('EditTags ', () => { +describe('EditTags ', () => { let appMockRender: AppMockRenderer; const sampleTags = ['coke', 'pepsi']; @@ -43,18 +42,11 @@ describe.skip('EditTags ', () => { appMockRender = createAppMockRenderer(); }); - it('renders no tags, and then edit', async () => { + it('renders no tags message', async () => { appMockRender.render(); expect(await screen.findByTestId('no-tags')).toBeInTheDocument(); - - userEvent.click(await screen.findByTestId('tag-list-edit-button')); - - await waitFor(() => { - expect(screen.queryByTestId('no-tags')).not.toBeInTheDocument(); - }); - - expect(await screen.findByTestId('edit-tags')).toBeInTheDocument(); + expect(await screen.findByTestId('tag-list-edit-button')).toBeInTheDocument(); }); it('edit tag from options on submit', async () => { From d3b81237ee3138e7a62ae34c19f65109b751f0b3 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 18 Jun 2024 09:49:50 +0200 Subject: [PATCH 031/127] [ML] AIOps Log Rate Analysis: Fix text field selection (#186176) If we analyse all detected text fields, we might run into performance issues with the `categorize_text` aggregation. Until this is resolved, we will rely on a predefined white list of supported text fields, for now set to `message` and `error.message`. --- .../queries/__mocks__/field_caps_pgbench.ts | 10 ++++++++++ .../queries/fetch_index_info.ts | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/x-pack/packages/ml/aiops_log_rate_analysis/queries/__mocks__/field_caps_pgbench.ts b/x-pack/packages/ml/aiops_log_rate_analysis/queries/__mocks__/field_caps_pgbench.ts index a4d85d8673971..bc3aec796ebe6 100644 --- a/x-pack/packages/ml/aiops_log_rate_analysis/queries/__mocks__/field_caps_pgbench.ts +++ b/x-pack/packages/ml/aiops_log_rate_analysis/queries/__mocks__/field_caps_pgbench.ts @@ -8,6 +8,16 @@ export const fieldCapsPgBenchMock = { indices: ['.ds-filebeat-8.2.0-2022.06.07-000082'], fields: { + // The next two fields are not in the original field caps response, + // but are added here to test the logic to ignore fields that are not + // in the white list. It's based on a real world example where the mapping + // included a double mapping of text+integer. + ignore_this_text_field: { + text: { type: 'text', metadata_field: false, searchable: true, aggregatable: false }, + }, + 'ignore_this_text_field.int': { + integer: { type: 'integer', metadata_field: false, searchable: true, aggregatable: true }, + }, 'kubernetes.node.uid': { keyword: { type: 'keyword', metadata_field: false, searchable: true, aggregatable: true }, }, diff --git a/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_index_info.ts b/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_index_info.ts index 1bb5b701fdd17..458fc630b5009 100644 --- a/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_index_info.ts +++ b/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_index_info.ts @@ -17,6 +17,12 @@ import { getTotalDocCountRequest } from './get_total_doc_count_request'; // TODO Consolidate with duplicate `fetchPValues` in // `x-pack/plugins/observability_solution/apm/server/routes/correlations/queries/fetch_duration_field_candidates.ts` +// Supported field names for text fields for log rate analysis. +// If we analyse all detected text fields, we might run into performance +// issues with the `categorize_text` aggregation. Until this is resolved, we +// rely on a predefined white list of supported text fields. +const TEXT_FIELD_WHITE_LIST = ['message', 'error.message']; + const SUPPORTED_ES_FIELD_TYPES = [ ES_FIELD_TYPES.KEYWORD, ES_FIELD_TYPES.IP, @@ -76,7 +82,7 @@ export const fetchIndexInfo = async ( acceptableFields.add(key); } - if (isTextField) { + if (isTextField && TEXT_FIELD_WHITE_LIST.includes(key)) { acceptableTextFields.add(key); } From 250c729087569cea009692ef2120fcee6842fed1 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 18 Jun 2024 10:07:07 +0200 Subject: [PATCH 032/127] [Discover][ES|QL] Reset selected fields when modifying the ES|QL query (#185997) - Closes https://github.com/elastic/kibana/issues/183961 ## Summary This PR updates the logic of resetting columns when modifying the ES|QL query. The previous implementation was added in https://github.com/elastic/kibana/pull/167492 and then changed in https://github.com/elastic/kibana/pull/177241. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Stratoula Kalafateli Co-authored-by: Matthias Wilhelm --- .buildkite/ftr_configs.yml | 1 + .../main/hooks/use_esql_mode.test.tsx | 58 ++++- .../application/main/hooks/use_esql_mode.ts | 66 ++--- .../apps/discover/esql/_esql_columns.ts | 245 ++++++++++++++++++ .../discover/{group4 => esql}/_esql_view.ts | 0 test/functional/apps/discover/esql/config.ts | 18 ++ test/functional/apps/discover/esql/index.ts | 26 ++ test/functional/apps/discover/group4/index.ts | 1 - test/functional/firefox/discover.config.ts | 1 + 9 files changed, 383 insertions(+), 33 deletions(-) create mode 100644 test/functional/apps/discover/esql/_esql_columns.ts rename test/functional/apps/discover/{group4 => esql}/_esql_view.ts (100%) create mode 100644 test/functional/apps/discover/esql/config.ts create mode 100644 test/functional/apps/discover/esql/index.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index aea151baae3a1..83ae94ada8d06 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -115,6 +115,7 @@ enabled: - test/functional/apps/discover/ccs_compatibility/config.ts - test/functional/apps/discover/classic/config.ts - test/functional/apps/discover/embeddable/config.ts + - test/functional/apps/discover/esql/config.ts - test/functional/apps/discover/group1/config.ts - test/functional/apps/discover/group2_data_grid1/config.ts - test/functional/apps/discover/group2_data_grid2/config.ts diff --git a/src/plugins/discover/public/application/main/hooks/use_esql_mode.test.tsx b/src/plugins/discover/public/application/main/hooks/use_esql_mode.test.tsx index 12109ea01a422..5f6d35afe8434 100644 --- a/src/plugins/discover/public/application/main/hooks/use_esql_mode.test.tsx +++ b/src/plugins/discover/public/application/main/hooks/use_esql_mode.test.tsx @@ -150,10 +150,11 @@ describe('useEsqlMode', () => { }); }); - test('changing an ES|QL query with same result columns should not change state when loading and finished', async () => { + test('changing an ES|QL query with same result columns but a different index pattern should change state when loading and finished', async () => { const { replaceUrlState, stateContainer } = renderHookWithContext(false); const documents$ = stateContainer.dataState.data$.documents$; stateContainer.dataState.data$.documents$.next(msgComplete); + replaceUrlState.mockReset(); documents$.next({ fetchStatus: FetchStatus.PARTIAL, @@ -166,7 +167,54 @@ describe('useEsqlMode', () => { ], query: { esql: 'from the-data-view-2' }, }); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + + await waitFor(() => { + expect(replaceUrlState).toHaveBeenCalledWith({ + columns: [], + }); + }); + }); + + test('changing a ES|QL query with no transformational commands should not change state when loading and finished if index pattern is the same', async () => { + const { replaceUrlState, stateContainer } = renderHookWithContext(false); + const documents$ = stateContainer.dataState.data$.documents$; + stateContainer.dataState.data$.documents$.next(msgComplete); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0)); + replaceUrlState.mockReset(); + + documents$.next({ + fetchStatus: FetchStatus.PARTIAL, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + // non transformational command + query: { esql: 'from the-data-view-title | where field1 > 0' }, + }); await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0)); + replaceUrlState.mockReset(); + + documents$.next({ + fetchStatus: FetchStatus.PARTIAL, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + // non transformational command + query: { esql: 'from the-data-view-title2 | where field1 > 0' }, + }); + await waitFor(() => { + expect(replaceUrlState).toHaveBeenCalledWith({ + columns: [], + }); + }); }); test('only changing an ES|QL query with same result columns should not change columns', async () => { @@ -268,7 +316,13 @@ describe('useEsqlMode', () => { query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' }, }); - expect(replaceUrlState).toHaveBeenCalledTimes(0); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + await waitFor(() => { + expect(replaceUrlState).toHaveBeenCalledWith({ + columns: ['field1', 'field2'], + }); + }); + replaceUrlState.mockReset(); documents$.next({ fetchStatus: FetchStatus.PARTIAL, diff --git a/src/plugins/discover/public/application/main/hooks/use_esql_mode.ts b/src/plugins/discover/public/application/main/hooks/use_esql_mode.ts index 2f3c99763fb04..841badc11537c 100644 --- a/src/plugins/discover/public/application/main/hooks/use_esql_mode.ts +++ b/src/plugins/discover/public/application/main/hooks/use_esql_mode.ts @@ -7,8 +7,8 @@ */ import { isEqual } from 'lodash'; -import { isOfAggregateQueryType, getAggregateQueryMode } from '@kbn/es-query'; -import { hasTransformationalCommand } from '@kbn/esql-utils'; +import { isOfAggregateQueryType } from '@kbn/es-query'; +import { hasTransformationalCommand, getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; import { useCallback, useEffect, useRef } from 'react'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import { switchMap } from 'rxjs'; @@ -31,9 +31,9 @@ export function useEsqlMode({ }) { const prev = useRef<{ query: string; - columns: string[]; + recentlyUpdatedToColumns: string[]; }>({ - columns: [], + recentlyUpdatedToColumns: [], query: '', }); const initialFetch = useRef(true); @@ -43,9 +43,10 @@ export function useEsqlMode({ if (prev.current.query) { // cleanup when it's not an ES|QL query prev.current = { - columns: [], + recentlyUpdatedToColumns: [], query: '', }; + initialFetch.current = true; } }, []); @@ -57,55 +58,60 @@ export function useEsqlMode({ if (!query || next.fetchStatus === FetchStatus.ERROR) { return; } + const sendComplete = () => { stateContainer.dataState.data$.documents$.next({ ...next, fetchStatus: FetchStatus.COMPLETE, }); }; + const { viewMode } = stateContainer.appState.getState(); - let nextColumns: string[] = []; const isEsqlQuery = isOfAggregateQueryType(query); - const hasResults = Boolean(next.result?.length); - let queryHasTransformationalCommands = false; - if ('esql' in query) { - if (hasTransformationalCommand(query.esql)) { - queryHasTransformationalCommands = true; - } - } if (isEsqlQuery) { - const language = getAggregateQueryMode(query); + const hasResults = Boolean(next.result?.length); + if (next.fetchStatus !== FetchStatus.PARTIAL) { return; } + let nextColumns: string[] = prev.current.recentlyUpdatedToColumns; + if (hasResults) { - // check if state needs to contain column transformation due to a different columns in the resultset const firstRow = next.result![0]; - const firstRowColumns = Object.keys(firstRow.raw).slice(0, MAX_NUM_OF_COLUMNS); - if (!queryHasTransformationalCommands) { - nextColumns = []; - initialFetch.current = false; + const firstRowColumns = Object.keys(firstRow.raw); + + if (hasTransformationalCommand(query.esql)) { + nextColumns = firstRowColumns.slice(0, MAX_NUM_OF_COLUMNS); } else { - nextColumns = firstRowColumns; - if (initialFetch.current && !prev.current.columns.length) { - prev.current.columns = firstRowColumns; - } + nextColumns = []; } } - const addColumnsToState = !isEqual(nextColumns, prev.current.columns); - const queryChanged = query[language] !== prev.current.query; + + if (initialFetch.current) { + initialFetch.current = false; + prev.current.query = query.esql; + prev.current.recentlyUpdatedToColumns = nextColumns; + } + + const indexPatternChanged = + getIndexPatternFromESQLQuery(query.esql) !== + getIndexPatternFromESQLQuery(prev.current.query); + + const addColumnsToState = + indexPatternChanged || !isEqual(nextColumns, prev.current.recentlyUpdatedToColumns); + const changeViewMode = viewMode !== getValidViewMode({ viewMode, isEsqlMode: true }); - if (!queryChanged || (!addColumnsToState && !changeViewMode)) { + + if (!indexPatternChanged && !addColumnsToState && !changeViewMode) { sendComplete(); return; } - if (queryChanged) { - prev.current.query = query[language]; - prev.current.columns = nextColumns; - } + prev.current.query = query.esql; + prev.current.recentlyUpdatedToColumns = nextColumns; + // just change URL state if necessary if (addColumnsToState || changeViewMode) { const nextState = { diff --git a/test/functional/apps/discover/esql/_esql_columns.ts b/test/functional/apps/discover/esql/_esql_columns.ts new file mode 100644 index 0000000000000..ba7f8447529ab --- /dev/null +++ b/test/functional/apps/discover/esql/_esql_columns.ts @@ -0,0 +1,245 @@ +/* + * Copyright 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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../ftr_provider_context'; + +const SAVED_SEARCH_NON_TRANSFORMATIONAL_INITIAL_COLUMNS = 'nonTransformationalInitialColumns'; +const SAVED_SEARCH_NON_TRANSFORMATIONAL_CUSTOM_COLUMNS = 'nonTransformationalCustomColumns'; +const SAVED_SEARCH_TRANSFORMATIONAL_INITIAL_COLUMNS = 'transformationalInitialColumns'; +const SAVED_SEARCH_TRANSFORMATIONAL_CUSTOM_COLUMNS = 'transformationalCustomColumns'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const security = getService('security'); + const dataGrid = getService('dataGrid'); + const browser = getService('browser'); + const monacoEditor = getService('monacoEditor'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects([ + 'common', + 'discover', + 'dashboard', + 'header', + 'timePicker', + 'unifiedFieldList', + ]); + + const defaultSettings = { + defaultIndex: 'logstash-*', + }; + + describe('discover esql columns', async function () { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.uiSettings.replace(defaultSettings); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.selectTextBaseLang(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + }); + + beforeEach(async () => { + await PageObjects.discover.clickNewSearchButton(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + }); + + it('should render initial columns for non-transformational commands correctly', async () => { + const columns = ['@timestamp', 'Document']; + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await browser.refresh(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await PageObjects.discover.saveSearch(SAVED_SEARCH_NON_TRANSFORMATIONAL_INITIAL_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + }); + + it('should render custom columns for non-transformational commands correctly', async () => { + const columns = ['bytes', 'extension']; + await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await browser.refresh(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await PageObjects.discover.saveSearch(SAVED_SEARCH_NON_TRANSFORMATIONAL_CUSTOM_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + }); + + it('should reset columns only if index pattern changes in non-transformational query', async () => { + const columns = ['@timestamp', 'Document']; + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await monacoEditor.setCodeEditorValue('from logstash-* | limit 1'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await monacoEditor.setCodeEditorValue('from logs* | limit 1'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['bytes']); + + // different index pattern => reset columns + await monacoEditor.setCodeEditorValue('from logstash-* | limit 1'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['extension']); + + // same index pattern => don't reset columns + await monacoEditor.setCodeEditorValue( + `${await monacoEditor.getCodeEditorValue()} | where bytes > 0` + ); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['extension']); + }); + + it('should render initial columns for a transformational command correctly', async () => { + const columns = ['ip', '@timestamp']; + await monacoEditor.setCodeEditorValue( + `${await monacoEditor.getCodeEditorValue()} | keep ip, @timestamp` + ); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await browser.refresh(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await PageObjects.discover.saveSearch(SAVED_SEARCH_TRANSFORMATIONAL_INITIAL_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + }); + + it('should render custom columns for a transformational command correctly', async () => { + const columns = ['ip', 'bytes']; + await monacoEditor.setCodeEditorValue( + `${await monacoEditor.getCodeEditorValue()} | keep ip, @timestamp, bytes` + ); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', '@timestamp', 'bytes']); + + await PageObjects.unifiedFieldList.clickFieldListItemRemove('@timestamp'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await browser.refresh(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + + await PageObjects.discover.saveSearch(SAVED_SEARCH_TRANSFORMATIONAL_CUSTOM_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(columns); + }); + + it('should reset columns if available fields or index pattern are different in transformational query', async () => { + await monacoEditor.setCodeEditorValue('from logstash-* | keep ip, @timestamp'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', '@timestamp']); + + // reset columns if available fields are different + await monacoEditor.setCodeEditorValue('from logstash-* | keep ip, @timestamp, bytes'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', '@timestamp', 'bytes']); + + // don't reset columns if available fields and index pattern are the same + await monacoEditor.setCodeEditorValue( + 'from logstash-* | keep ip, @timestamp, bytes | limit 1' + ); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', '@timestamp', 'bytes']); + await PageObjects.unifiedFieldList.clickFieldListItemRemove('@timestamp'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', 'bytes']); + + // reset columns if index pattern is different + await monacoEditor.setCodeEditorValue('from logs* | keep ip, @timestamp, bytes | limit 1'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', '@timestamp', 'bytes']); + }); + + it('should restore columns correctly when switching between saved searches', async () => { + await PageObjects.discover.loadSavedSearch(SAVED_SEARCH_NON_TRANSFORMATIONAL_INITIAL_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']); + + await PageObjects.discover.loadSavedSearch(SAVED_SEARCH_NON_TRANSFORMATIONAL_CUSTOM_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['bytes', 'extension']); + + await PageObjects.discover.loadSavedSearch(SAVED_SEARCH_TRANSFORMATIONAL_INITIAL_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', '@timestamp']); + + await PageObjects.discover.loadSavedSearch(SAVED_SEARCH_TRANSFORMATIONAL_CUSTOM_COLUMNS); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['ip', 'bytes']); + + await PageObjects.discover.clickNewSearchButton(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']); + }); + }); +} diff --git a/test/functional/apps/discover/group4/_esql_view.ts b/test/functional/apps/discover/esql/_esql_view.ts similarity index 100% rename from test/functional/apps/discover/group4/_esql_view.ts rename to test/functional/apps/discover/esql/_esql_view.ts diff --git a/test/functional/apps/discover/esql/config.ts b/test/functional/apps/discover/esql/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/discover/esql/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/discover/esql/index.ts b/test/functional/apps/discover/esql/index.ts new file mode 100644 index 0000000000000..5ba21ac0a8aa2 --- /dev/null +++ b/test/functional/apps/discover/esql/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const browser = getService('browser'); + + describe('discover/esql', function () { + before(async function () { + await browser.setWindowSize(1600, 1200); + }); + + after(async function unloadMakelogs() { + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + loadTestFile(require.resolve('./_esql_columns')); + loadTestFile(require.resolve('./_esql_view')); + }); +} diff --git a/test/functional/apps/discover/group4/index.ts b/test/functional/apps/discover/group4/index.ts index 211b4501ed329..bb685ce8cbe6b 100644 --- a/test/functional/apps/discover/group4/index.ts +++ b/test/functional/apps/discover/group4/index.ts @@ -22,7 +22,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_discover_fields_api')); loadTestFile(require.resolve('./_adhoc_data_views')); - loadTestFile(require.resolve('./_esql_view')); loadTestFile(require.resolve('./_date_nested')); loadTestFile(require.resolve('./_chart_hidden')); loadTestFile(require.resolve('./_context_encoded_url_params')); diff --git a/test/functional/firefox/discover.config.ts b/test/functional/firefox/discover.config.ts index 5c9f9c0939754..61ffcb9fd21bf 100644 --- a/test/functional/firefox/discover.config.ts +++ b/test/functional/firefox/discover.config.ts @@ -18,6 +18,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [ require.resolve('../apps/discover/classic'), + require.resolve('../apps/discover/esql'), require.resolve('../apps/discover/group1'), require.resolve('../apps/discover/group2_data_grid1'), require.resolve('../apps/discover/group2_data_grid2'), From 202a774d466ed6a1dbbfe8bbb9fa7783bb6ff447 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Tue, 18 Jun 2024 10:26:10 +0200 Subject: [PATCH 033/127] [ES|QL] Editor supports integrations (#184716) ## Summary Supporting integrations in the editor using the native monaco suggestions system. ![meow](https://github.com/elastic/kibana/assets/17003240/0e72ebd0-c71e-4282-b444-6106feb3926c) This PR: - Uses a different icon for the simple indices, I didn't like the previous one - Adds support of integrations using the built in monaco api capabilities - The integrations have a different icon and a different indicator (Integrations vs Indices) - I am fetching the integrations from the api that was given to me. The api is hardcoded because is very difficult to get it from the fleet plugin, I asked from the team to move their constants in a package https://github.com/elastic/kibana/issues/186061 ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/autocomplete/autocomplete.test.ts | 42 +++++++++++++--- .../src/autocomplete/autocomplete.ts | 45 +++++++++++++++-- .../src/autocomplete/factories.ts | 24 ++++++--- .../src/autocomplete/helper.ts | 10 +++- .../src/shared/types.ts | 10 +++- packages/kbn-text-based-editor/src/helpers.ts | 49 +++++++++++++++++-- .../src/text_based_languages_editor.tsx | 5 +- 7 files changed, 159 insertions(+), 26 deletions(-) diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts index efff60c382d34..528e5f338b53e 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts @@ -21,6 +21,16 @@ import { getParamAtPosition } from './helper'; import { nonNullable } from '../shared/helpers'; import { METADATA_FIELDS } from '../shared/constants'; +interface Integration { + name: string; + hidden: boolean; + title?: string; + dataStreams: Array<{ + name: string; + title?: string; + }>; +} + const triggerCharacters = [',', '(', '=', ' ']; const fields: Array<{ name: string; type: string; suggestedAs?: string }> = [ @@ -42,13 +52,10 @@ const fields: Array<{ name: string; type: string; suggestedAs?: string }> = [ { name: 'kubernetes.something.something', type: 'number' }, ]; -const indexes = ( - [] as Array<{ name: string; hidden: boolean; suggestedAs: string | undefined }> -).concat( +const indexes = ([] as Array<{ name: string; hidden: boolean; suggestedAs?: string }>).concat( ['a', 'index', 'otherIndex', '.secretIndex', 'my-index'].map((name) => ({ name, hidden: name.startsWith('.'), - suggestedAs: undefined, })), ['my-index[quoted]', 'my-index$', 'my_index{}'].map((name) => ({ name, @@ -56,6 +63,18 @@ const indexes = ( suggestedAs: `\`${name}\``, })) ); + +const integrations: Integration[] = ['nginx', 'k8s'].map((name) => ({ + name, + hidden: false, + title: `integration-${name}`, + dataStreams: [ + { + name: `${name}-1`, + title: `integration-${name}-1`, + }, + ], +})); const policies = [ { name: 'policy', @@ -347,9 +366,8 @@ describe('autocomplete', () => { }); describe('from', () => { - const suggestedIndexes = indexes - .filter(({ hidden }) => !hidden) - .map(({ name, suggestedAs }) => suggestedAs || name); + const suggestedIndexes = indexes.filter(({ hidden }) => !hidden).map(({ name }) => name); + // Monaco will filter further down here testSuggestions( 'f', @@ -372,6 +390,16 @@ describe('autocomplete', () => { METADATA_FIELDS.filter((field) => field !== '_index'), ' ' ); + + // with integrations support + const dataSources = indexes.concat(integrations); + const suggestedDataSources = dataSources + .filter(({ hidden }) => !hidden) + .map(({ name }) => name); + + testSuggestions('from ', suggestedDataSources, '', [undefined, dataSources, undefined]); + testSuggestions('from a,', suggestedDataSources, '', [undefined, dataSources, undefined]); + testSuggestions('from *,', suggestedDataSources, '', [undefined, dataSources, undefined]); }); describe('show', () => { diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts index e753255624383..ba2f180fb51f6 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts @@ -84,11 +84,19 @@ import { getFunctionsToIgnoreForStats, getParamAtPosition, getQueryForFields, + getSourcesFromCommands, isAggFunctionUsedAlready, } from './helper'; import { FunctionArgSignature } from '../definitions/types'; type GetSourceFn = () => Promise; +type GetDataSourceFn = (sourceName: string) => Promise< + | { + name: string; + dataStreams?: Array<{ name: string; title?: string }>; + } + | undefined +>; type GetFieldsByTypeFn = ( type: string | string[], ignored?: string[] @@ -203,6 +211,7 @@ export async function suggest( resourceRetriever ); const getSources = getSourcesRetriever(resourceRetriever); + const getDatastreamsForIntegration = getDatastreamsForIntegrationRetriever(resourceRetriever); const { getPolicies, getPolicyMetadata } = getPolicyRetriever(resourceRetriever); if (astContext.type === 'newCommand') { @@ -223,6 +232,7 @@ export async function suggest( ast, astContext, getSources, + getDatastreamsForIntegration, getFieldsByType, getFieldsMap, getPolicies, @@ -303,7 +313,21 @@ function getSourcesRetriever(resourceRetriever?: ESQLCallbacks) { return async () => { const list = (await helper()) || []; // hide indexes that start with . - return buildSourcesDefinitions(list.filter(({ hidden }) => !hidden).map(({ name }) => name)); + return buildSourcesDefinitions( + list + .filter(({ hidden }) => !hidden) + .map(({ name, dataStreams, title }) => { + return { name, isIntegration: Boolean(dataStreams && dataStreams.length), title }; + }) + ); + }; +} + +function getDatastreamsForIntegrationRetriever(resourceRetriever?: ESQLCallbacks) { + const helper = getSourcesHelper(resourceRetriever); + return async (sourceName: string) => { + const list = (await helper()) || []; + return list.find(({ name }) => name === sourceName); }; } @@ -475,6 +499,7 @@ async function getExpressionSuggestionsByType( node: ESQLSingleAstItem | undefined; }, getSources: GetSourceFn, + getDatastreamsForIntegration: GetDataSourceFn, getFieldsByType: GetFieldsByTypeFn, getFieldsMap: GetFieldsMapFn, getPolicies: GetPoliciesFn, @@ -829,9 +854,21 @@ async function getExpressionSuggestionsByType( const policies = await getPolicies(); suggestions.push(...(policies.length ? policies : [buildNoPoliciesAvailableDefinition()])); } else { - // FROM - // @TODO: filter down the suggestions here based on other existing sources defined - suggestions.push(...(await getSources())); + const index = getSourcesFromCommands(commands, 'index'); + // This is going to be empty for simple indices, and not empty for integrations + if (index && index.text) { + const source = index.text.replace(EDITOR_MARKER, ''); + const dataSource = await getDatastreamsForIntegration(source); + const newDefinitions = buildSourcesDefinitions( + dataSource?.dataStreams?.map(({ name }) => ({ name, isIntegration: false })) || [] + ); + suggestions.push(...newDefinitions); + } else { + // FROM + // @TODO: filter down the suggestions here based on other existing sources defined + const sourcesDefinitions = await getSources(); + suggestions.push(...sourcesDefinitions); + } } } } diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts index 4b2e74729db78..34c28b4b50d09 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts @@ -143,14 +143,22 @@ export const buildVariablesDefinitions = (variables: string[]): SuggestionRawDef sortText: 'D', })); -export const buildSourcesDefinitions = (sources: string[]): SuggestionRawDefinition[] => - sources.map((label) => ({ - label, - text: getSafeInsertText(label, { dashSupported: true }), - kind: 'Reference', - detail: i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.sourceDefinition', { - defaultMessage: `Index`, - }), +export const buildSourcesDefinitions = ( + sources: Array<{ name: string; isIntegration: boolean; title?: string }> +): SuggestionRawDefinition[] => + sources.map(({ name, isIntegration, title }) => ({ + label: title ?? name, + text: name, + isSnippet: isIntegration, + ...(isIntegration && { command: TRIGGER_SUGGESTION_COMMAND }), + kind: isIntegration ? 'Class' : 'Issue', + detail: isIntegration + ? i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.integrationDefinition', { + defaultMessage: `Integration`, + }) + : i18n.translate('kbn-esql-validation-autocomplete.esql.autocomplete.sourceDefinition', { + defaultMessage: `Index`, + }), sortText: 'A', })); diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts index 7bba3a5ab15ec..fa6e364c78ca9 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { ESQLAstItem, ESQLCommand, ESQLFunction } from '@kbn/esql-ast'; +import type { ESQLAstItem, ESQLCommand, ESQLFunction, ESQLSource } from '@kbn/esql-ast'; import { FunctionDefinition } from '../definitions/types'; import { getFunctionDefinition, isAssignment, isFunctionItem } from '../shared/helpers'; @@ -63,3 +63,11 @@ export function getQueryForFields(queryString: string, commands: ESQLCommand[]) ? '' : queryString; } + +export function getSourcesFromCommands(commands: ESQLCommand[], sourceType: 'index' | 'policy') { + const fromCommand = commands.find(({ name }) => name === 'from'); + const args = (fromCommand?.args ?? []) as ESQLSource[]; + const sources = args.filter((arg) => arg.sourceType === sourceType); + + return sources.length === 1 ? sources[0] : undefined; +} diff --git a/packages/kbn-esql-validation-autocomplete/src/shared/types.ts b/packages/kbn-esql-validation-autocomplete/src/shared/types.ts index 758218c52062f..d2ce2e4b104df 100644 --- a/packages/kbn-esql-validation-autocomplete/src/shared/types.ts +++ b/packages/kbn-esql-validation-autocomplete/src/shared/types.ts @@ -11,7 +11,15 @@ type CallbackFn = (ctx?: Options) => Result[] | P /** @public **/ export interface ESQLCallbacks { - getSources?: CallbackFn<{}, { name: string; hidden: boolean }>; + getSources?: CallbackFn< + {}, + { + name: string; + hidden: boolean; + title?: string; + dataStreams?: Array<{ name: string; title?: string }>; + } + >; getFieldsFor?: CallbackFn<{ query: string }, { name: string; type: string }>; getPolicies?: CallbackFn< {}, diff --git a/packages/kbn-text-based-editor/src/helpers.ts b/packages/kbn-text-based-editor/src/helpers.ts index 8d4943800f750..59dffbd29e07f 100644 --- a/packages/kbn-text-based-editor/src/helpers.ts +++ b/packages/kbn-text-based-editor/src/helpers.ts @@ -9,12 +9,27 @@ import { useRef } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import { monaco } from '@kbn/monaco'; +import type { CoreStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { MapCache } from 'lodash'; export type MonacoMessage = monaco.editor.IMarkerData; +interface IntegrationsResponse { + items: Array<{ + name: string; + title?: string; + dataStreams: Array<{ + name: string; + title?: string; + }>; + }>; +} + +const INTEGRATIONS_API = '/api/fleet/epm/packages/installed'; +const API_VERSION = '2023-10-31'; + export const useDebounceWithOptions = ( fn: Function, { skipFirstRender }: { skipFirstRender: boolean } = { skipFirstRender: false }, @@ -227,10 +242,38 @@ export const clearCacheWhenOld = (cache: MapCache, esqlQuery: string) => { } }; -export const getESQLSources = async (dataViews: DataViewsPublicPluginStart) => { - const [remoteIndices, localIndices] = await Promise.all([ +const getIntegrations = async (core: CoreStart) => { + const fleetCapabilities = core.application.capabilities.fleet; + if (!fleetCapabilities?.read) { + return []; + } + // Ideally we should use the Fleet plugin constants to fetch the integrations + // import { EPM_API_ROUTES, API_VERSIONS } from '@kbn/fleet-plugin/common'; + // but it complicates things as we need to use an x-pack plugin as dependency to get 2 constants + // and this needs to be done in various places in the codebase which use the editor + // https://github.com/elastic/kibana/issues/186061 + const response = (await core.http + .get(INTEGRATIONS_API, { query: undefined, version: API_VERSION }) + .catch((error) => { + // eslint-disable-next-line no-console + console.error('Failed to fetch integrations', error); + })) as IntegrationsResponse; + + return ( + response?.items?.map((source) => ({ + name: source.name, + hidden: false, + title: source.title, + dataStreams: source.dataStreams, + })) ?? [] + ); +}; + +export const getESQLSources = async (dataViews: DataViewsPublicPluginStart, core: CoreStart) => { + const [remoteIndices, localIndices, integrations] = await Promise.all([ getRemoteIndicesList(dataViews), getIndicesList(dataViews), + getIntegrations(core), ]); - return [...localIndices, ...remoteIndices]; + return [...localIndices, ...remoteIndices, ...integrations]; }; diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 686f508cdac1e..b3729118f6e99 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -391,7 +391,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const { cache: dataSourcesCache, memoizedSources } = useMemo(() => { const fn = memoize( - (...args: [DataViewsPublicPluginStart]) => ({ + (...args: [DataViewsPublicPluginStart, CoreStart]) => ({ timestamp: Date.now(), result: getESQLSources(...args), }), @@ -405,7 +405,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const callbacks: ESQLCallbacks = { getSources: async () => { clearCacheWhenOld(dataSourcesCache, queryString); - const sources = await memoizedSources(dataViews).result; + const sources = await memoizedSources(dataViews, core).result; return sources; }, getFieldsFor: async ({ query: queryToExecute }: { query?: string } | undefined = {}) => { @@ -445,6 +445,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ memoizedSources, dataSourcesCache, dataViews, + core, esqlFieldsCache, memoizedFieldsFromESQL, expressions, From 4f3e12e1502ae0ae8767a33876c2041d79021576 Mon Sep 17 00:00:00 2001 From: Bharat Pasupula <123897612+bhapas@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:55:41 +0200 Subject: [PATCH 034/127] [Security GenAI][Integration Assistant] Fix bugs in ecs_mapping graph (#186301) ## Summary This PR holds multiple fixes for the `ecs_mapping` graph - Closes #185038 - Closes #185037 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/graphs/ecs/prompts.ts | 11 ++-- .../server/graphs/ecs/validate.test.ts | 52 +++++++++++++++++++ .../server/graphs/ecs/validate.ts | 6 ++- 3 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts index 56b985d2e0b7c..f336b2cde4b48 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts @@ -30,11 +30,12 @@ Go through each value step by step and modify it with the following process: 3. If no relevant ECS field is found, the value should just be replaced with "null" rather than a new object. 4. Only if a relevant ECS field is found replace the value with a new object that has the keys "target", "confidence", "date_format" and "type". 5. The object key "target" should be set to be the full path of the ECS field name you think it matches. Set the object key "type" to be either "string", "boolean", "number" or "date" depending on what was detected as the example value. -6. If the type "date" is used, then set date_format to be an array of one or more of the equivilant JAVA date formats that fits the example value. If the type is not date then date_format should be set to an empty array []. -7. For each key that you set a target ECS field, also score the confidence you have in that the target field is correct, use a float between 0.0 and 1.0 and set the value in the nested "confidence" key. -8. When you want to use an ECS field as a value for a target, but another field already has the same ECS field as its target, try to find another fitting ECS field. If none is found then the one you are least confident about should have the object replaced with null. -9. If you are not confident for a specific field, you should always set the value to null. -10. These {package_name} log samples are based on source and destination type data, prioritize these compared to other related ECS fields like host.* and observer.*. +6. If the type "date" is used, then set date_format to be an array of one or more of the equivilant JAVA date formats that fits the example value, including those with nanosecond precision. If the type is not date then date_format should be set to an empty array []. +7. Use a custom date pattern if the built-in date format patterns do not match the example value , including those with nanosecond precision. +8. For each key that you set a target ECS field, also score the confidence you have in that the target field is correct, use a float between 0.0 and 1.0 and set the value in the nested "confidence" key. +9. When you want to use an ECS field as a value for a target, but another field already has the same ECS field as its target, try to find another fitting ECS field. If none is found then the one you are least confident about should have the object replaced with null. +10. If you are not confident for a specific field, you should always set the value to null. +11. These {package_name} log samples are based on source and destination type data, prioritize these compared to other related ECS fields like host.* and observer.*. You ALWAYS follow these guidelines when writing your response: diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts new file mode 100644 index 0000000000000..1fac2a93ce53c --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { processMapping } from './validate'; + +describe('Testing ecs handler', () => { + it('processMapping()', async () => { + const path: string[] = []; + const value = { + checkpoint: { + firewall: { + product: null, + sequencenum: null, + subject: null, + ifdir: null, + origin: { + target: 'source.address', + confidence: 0.9, + type: 'string', + date_formats: [], + }, + flags: null, + sendtotrackerasadvancedauditlog: null, + originsicname: null, + version: null, + administrator: { + target: 'user.name', + confidence: 0.8, + type: 'string', + date_formats: [], + }, + foo: { + target: null, // Invalid value , to be skipped + confidence: 0.8, + type: 'string', + date_formats: [], + }, + }, + }, + }; + const output: Record = {}; + await processMapping(path, value, output); + expect(output).toEqual({ + 'source.address': [['checkpoint', 'firewall', 'origin']], + 'user.name': [['checkpoint', 'firewall', 'administrator']], + }); + }); +}); diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts index 0a01b1f59dcf3..15d3db7c95551 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts @@ -49,7 +49,11 @@ function findMissingFields(formattedSamples: string, ecsMapping: AnyObject): str return missingKeys; } -function processMapping(path: string[], value: any, output: Record): void { +export function processMapping( + path: string[], + value: any, + output: Record +): void { if (typeof value === 'object' && value !== null) { if (!Array.isArray(value)) { // If the value is a dict with all the keys returned for each source field, this is the full path of the field. From 3639308d37594c4c9631e0a8e079f2cff1b5de1c Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Tue, 18 Jun 2024 10:57:55 +0200 Subject: [PATCH 035/127] =?UTF-8?q?Upgrade=20micromatch@4.0.5=E2=86=924.0.?= =?UTF-8?q?7=20(#186064)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Upgrades the `micromatch` production dependency from v4.0.5 to v4.0.7. Also removes the `@langtrase/typescript-sdk` dependency, as it is not currently being referenced. --- package.json | 3 +- yarn.lock | 140 ++++++++------------------------------------------- 2 files changed, 23 insertions(+), 120 deletions(-) diff --git a/package.json b/package.json index 74d8629a2b1fa..e8d694bb323e8 100644 --- a/package.json +++ b/package.json @@ -933,7 +933,6 @@ "@langchain/langgraph": "^0.0.23", "@langchain/openai": "^0.0.34", "@langtrase/trace-attributes": "^3.0.8", - "@langtrase/typescript-sdk": "^2.2.1", "@launchdarkly/node-server-sdk": "^9.4.5", "@loaders.gl/core": "^3.4.7", "@loaders.gl/json": "^3.4.7", @@ -1669,7 +1668,7 @@ "lmdb": "^2.9.2", "loader-utils": "^2.0.4", "marge": "^1.0.1", - "micromatch": "^4.0.5", + "micromatch": "^4.0.7", "mini-css-extract-plugin": "1.1.0", "minimist": "^1.2.6", "mocha": "^10.1.0", diff --git a/yarn.lock b/yarn.lock index 1481570519f4a..abf9faf49c8ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6966,20 +6966,6 @@ dependencies: ncp "^2.0.0" -"@langtrase/typescript-sdk@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@langtrase/typescript-sdk/-/typescript-sdk-2.2.1.tgz#8ec60290b9882e161bc42bd51cf0a72396438633" - integrity sha512-CRzhOcGMLv68ICvENDBQ/PWIHyBNlc6lNBaqF9EM/s+HUusSPnBmvQ+nGObqpPR+uo7m9hDRRUmUXOlAooj0PQ== - dependencies: - "@langtrase/trace-attributes" "^3.0.8" - "@opentelemetry/api" "^1.7.0" - "@opentelemetry/instrumentation" "^0.49.1" - "@opentelemetry/sdk-trace-base" "^1.22.0" - "@opentelemetry/sdk-trace-node" "^1.22.0" - axios "^1.6.7" - node-loader "^2.0.0" - tiktoken "^1.0.13" - "@launchdarkly/js-sdk-common@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@launchdarkly/js-sdk-common/-/js-sdk-common-2.5.0.tgz#d1dc595034bf6ee09b0313add5b8901fe9b82f26" @@ -7629,13 +7615,6 @@ dependencies: "@octokit/openapi-types" "^18.0.0" -"@opentelemetry/api-logs@0.49.1": - version "0.49.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.49.1.tgz#51a66ed5eb5eeeafffbd36c1713aa91cbfdd5259" - integrity sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q== - dependencies: - "@opentelemetry/api" "^1.0.0" - "@opentelemetry/api-metrics@0.31.0", "@opentelemetry/api-metrics@^0.31.0": version "0.31.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api-metrics/-/api-metrics-0.31.0.tgz#0ed4cf4d7c731f968721c2b303eaf5e9fd42f736" @@ -7643,16 +7622,11 @@ dependencies: "@opentelemetry/api" "^1.0.0" -"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.1.0", "@opentelemetry/api@^1.4.1", "@opentelemetry/api@^1.7.0": +"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.1.0", "@opentelemetry/api@^1.4.1": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== -"@opentelemetry/context-async-hooks@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.24.0.tgz#f5f8cc15038d293a8e9b570543c1f36aa4ee17ec" - integrity sha512-s7xaQ9ifDpJvwbWRLkZD/J5hY35w+MECm4TQUkg6szRcny9lf6oVhWij4w3JJFQgvHQMXU7oXOpX8Z05HxV/8g== - "@opentelemetry/core@1.15.0": version "1.15.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.0.tgz#2ba928df0443732825a72a766c2edae9a7f9863f" @@ -7715,18 +7689,6 @@ "@opentelemetry/core" "1.5.0" "@opentelemetry/sdk-metrics-base" "0.31.0" -"@opentelemetry/instrumentation@^0.49.1": - version "0.49.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.49.1.tgz#1b95e5f9448a96e7af97e03846772829439a9a91" - integrity sha512-0DLtWtaIppuNNRRllSD4bjU8ZIiLp1cDXvJEbp752/Zf+y3gaLNaoGRGIlX4UHhcsrmtL+P2qxi3Hodi8VuKiQ== - dependencies: - "@opentelemetry/api-logs" "0.49.1" - "@types/shimmer" "^1.0.2" - import-in-the-middle "1.7.1" - require-in-the-middle "^7.1.1" - semver "^7.5.2" - shimmer "^1.2.1" - "@opentelemetry/otlp-exporter-base@0.34.0": version "0.34.0" resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.34.0.tgz#c6020b63590d4b8ac3833eda345a6f582fa014b1" @@ -7754,20 +7716,6 @@ "@opentelemetry/sdk-metrics" "1.8.0" "@opentelemetry/sdk-trace-base" "1.8.0" -"@opentelemetry/propagator-b3@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-1.24.0.tgz#88a2ffede42ac6df7c409bacec0c9f9cc181bc13" - integrity sha512-7TMIDE4+NO5vnkor+zned42wqca+hmhW5gWKhmYjUHC5B5uojo1PvtmBrd7kigFu96XvL4ZUWVzibWRWIQ/++Q== - dependencies: - "@opentelemetry/core" "1.24.0" - -"@opentelemetry/propagator-jaeger@1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.24.0.tgz#e67fe6f8f2f1d74335909a7f7352d0761039ab79" - integrity sha512-r3MX3AmJiUeiWTXSDOdwBeaO+ahvWcFCpuKxmhhsH8Q8LqDnjhNd3krqBh4Qsq9wa0WhWtiQaDs/NOCWoMOlOw== - dependencies: - "@opentelemetry/core" "1.24.0" - "@opentelemetry/resources@1.15.0": version "1.15.0" resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.0.tgz#748a6ae9017636b8b30f5dee1fff3e166e51f63d" @@ -7830,15 +7778,6 @@ lodash.merge "^4.6.2" tslib "^2.3.1" -"@opentelemetry/sdk-trace-base@1.24.0", "@opentelemetry/sdk-trace-base@^1.22.0", "@opentelemetry/sdk-trace-base@^1.24.0": - version "1.24.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz#e2de869e33fd224f6d9f39bafa4172074d1086c8" - integrity sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg== - dependencies: - "@opentelemetry/core" "1.24.0" - "@opentelemetry/resources" "1.24.0" - "@opentelemetry/semantic-conventions" "1.24.0" - "@opentelemetry/sdk-trace-base@1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.8.0.tgz#70713aab90978a16dea188c8335209f857be7384" @@ -7848,17 +7787,14 @@ "@opentelemetry/resources" "1.8.0" "@opentelemetry/semantic-conventions" "1.8.0" -"@opentelemetry/sdk-trace-node@^1.22.0": +"@opentelemetry/sdk-trace-base@^1.24.0": version "1.24.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.24.0.tgz#34c56f092f98a16e0e045152c9a4baf50ed8dcee" - integrity sha512-QgByHmM9uloTpcYEEyW9YJEIMKHFSIM677RH9pJPWWwtM2NQFbEp/8HIJw80Ymtaz6cAxg1Kay1ByqIVzq3t5g== + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz#e2de869e33fd224f6d9f39bafa4172074d1086c8" + integrity sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg== dependencies: - "@opentelemetry/context-async-hooks" "1.24.0" "@opentelemetry/core" "1.24.0" - "@opentelemetry/propagator-b3" "1.24.0" - "@opentelemetry/propagator-jaeger" "1.24.0" - "@opentelemetry/sdk-trace-base" "1.24.0" - semver "^7.5.2" + "@opentelemetry/resources" "1.24.0" + "@opentelemetry/semantic-conventions" "1.24.0" "@opentelemetry/semantic-conventions@1.15.0": version "1.15.0" @@ -10961,11 +10897,6 @@ resolved "https://registry.yarnpkg.com/@types/set-value/-/set-value-2.0.0.tgz#63d386b103926dcf49b50e16e0f6dd49983046be" integrity sha512-k8dCJEC80F/mbsIOZ5Hj3YSzTVVVBwMdtP/M9Rtc2TM4F5etVd+2UG8QUiAUfbXm4fABedL2tBZnrBheY7UwpA== -"@types/shimmer@^1.0.2": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.5.tgz#491d8984d4510e550bfeb02d518791d7f59d2b88" - integrity sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww== - "@types/sinon@^7.0.13": version "7.0.13" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.0.13.tgz#ca039c23a9e27ebea53e0901ef928ea2a1a6d313" @@ -13164,7 +13095,7 @@ brace@0.11.1, brace@^0.11.1: braces@^2.3.1: version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" @@ -13178,12 +13109,12 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" breadth-filter@^2.0.0: version "2.0.0" @@ -17757,10 +17688,10 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -19613,16 +19544,6 @@ import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-in-the-middle@1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz#3e111ff79c639d0bde459bd7ba29dd9fdf357364" - integrity sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg== - dependencies: - acorn "^8.8.2" - acorn-import-assertions "^1.9.0" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - import-in-the-middle@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.8.0.tgz#c94d88d53701de9a248f9710b41f533e67f598a4" @@ -22827,7 +22748,7 @@ micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" @@ -22844,12 +22765,12 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" miller-rabin@^4.0.0: @@ -23797,13 +23718,6 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-loader@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-loader/-/node-loader-2.0.0.tgz#9109a6d828703fd3e0aa03c1baec12a798071562" - integrity sha512-I5VN34NO4/5UYJaUBtkrODPWxbobrE4hgDqPrjB25yPkonFhCmZ146vTH+Zg417E9Iwoh1l/MbRs1apc5J295Q== - dependencies: - loader-utils "^2.0.0" - node-preload@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" @@ -28301,11 +28215,6 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" -shimmer@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" - integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== - should-equal@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" @@ -29990,11 +29899,6 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371" integrity sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E= -tiktoken@^1.0.13: - version "1.0.14" - resolved "https://registry.yarnpkg.com/tiktoken/-/tiktoken-1.0.14.tgz#1263821f4ba0a4ec71604db8608a3accd43001c9" - integrity sha512-g5zd5r/DoH8Kw0fiYbYpVhb6WO8BHO1unXqmBBWKwoT17HwSounnDtMDFUKm2Pko8U47sjQarOe+9aUrnqmmTg== - time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" From 3d09eaa6fc7f1065e5bb0356f952058b9750d271 Mon Sep 17 00:00:00 2001 From: elena-shostak <165678770+elena-shostak@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:10:52 +0200 Subject: [PATCH 036/127] [Spaces] Passing default solution from cloud onboarding process (#185926) ## Summary Passing default solution from cloud onboarding process. 1. Renaming. Solution changes are not released yet, would be shipped with `8.15`, so it's fine to do it. - `search` -> `es` - `observability` -> `oblt` - Adjusted telemetry accordingly 2. Added `cloud` as optional dependency to `spaces` plugin to use `onboarding.defaultSolution` passed through setup contract. ### How to test 1. Set `xpack.cloud.onboarding.default_solution` to `es | oblt | security` 2. Check that default space was created with provided solution `GET kbn:/api/spaces/space/default` ### Checklist - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) __Fixes: https://github.com/elastic/kibana/issues/184999__ --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- docs/api/spaces-management/get.asciidoc | 2 +- docs/api/spaces-management/get_all.asciidoc | 2 +- docs/api/spaces-management/post.asciidoc | 2 +- docs/api/spaces-management/put.asciidoc | 2 +- src/plugins/navigation/public/plugin.test.ts | 4 +-- src/plugins/navigation/public/plugin.tsx | 16 ++++++------ x-pack/plugins/security/server/plugin.ts | 3 ++- .../plugins/spaces/common/types/space/v1.ts | 4 ++- x-pack/plugins/spaces/kibana.jsonc | 3 ++- .../create_default_space.test.ts | 25 ++++++++++++++++++ .../default_space/create_default_space.ts | 5 +++- .../default_space/default_space_service.ts | 5 +++- .../spaces/server/lib/space_schema.test.ts | 8 +++--- .../plugins/spaces/server/lib/space_schema.ts | 4 +-- x-pack/plugins/spaces/server/plugin.test.ts | 24 +++++++++++++++++ x-pack/plugins/spaces/server/plugin.ts | 3 +++ .../saved_objects/saved_objects_service.ts | 4 +-- .../spaces_client/spaces_client.test.ts | 26 +++++++++---------- .../spaces_usage_collector.ts | 6 ++--- x-pack/plugins/spaces/tsconfig.json | 1 + .../schema/xpack_plugins.json | 4 +-- .../common/suites/create.ts | 4 +-- .../spaces_only/telemetry/telemetry.ts | 6 ++--- 23 files changed, 113 insertions(+), 50 deletions(-) diff --git a/docs/api/spaces-management/get.asciidoc b/docs/api/spaces-management/get.asciidoc index d2dbeb0a3f4b4..f3e3462b2e0da 100644 --- a/docs/api/spaces-management/get.asciidoc +++ b/docs/api/spaces-management/get.asciidoc @@ -32,6 +32,6 @@ The API returns the following: "initials": "MK", "disabledFeatures": [], "imageUrl": "", - "solution": "search" + "solution": "es" } -------------------------------------------------- diff --git a/docs/api/spaces-management/get_all.asciidoc b/docs/api/spaces-management/get_all.asciidoc index 0fd332c12b739..92a65d670ad87 100644 --- a/docs/api/spaces-management/get_all.asciidoc +++ b/docs/api/spaces-management/get_all.asciidoc @@ -72,7 +72,7 @@ The API returns the following: "initials": "MK", "disabledFeatures": ["discover"], "imageUrl": "", - "solution": "observability" + "solution": "oblt" } ] -------------------------------------------------- diff --git a/docs/api/spaces-management/post.asciidoc b/docs/api/spaces-management/post.asciidoc index b72d4df79c3d6..4c5976249f80e 100644 --- a/docs/api/spaces-management/post.asciidoc +++ b/docs/api/spaces-management/post.asciidoc @@ -37,7 +37,7 @@ experimental[] Create a {kib} space. For best results, your image should be 64x64. Images will not be optimized by this API call, so care should be taken when using custom images. `solution`:: - (Optional, string) The solution defined for the space. Can be one of `security`, `observability`, `search`, `classic` + (Optional, string) The solution defined for the space. Can be one of `security`, `oblt`, `es`, `classic` [[spaces-api-post-response-codes]] ==== Response codes diff --git a/docs/api/spaces-management/put.asciidoc b/docs/api/spaces-management/put.asciidoc index 0d1c8d5f2e779..88d0d41114eb5 100644 --- a/docs/api/spaces-management/put.asciidoc +++ b/docs/api/spaces-management/put.asciidoc @@ -37,7 +37,7 @@ experimental[] Update an existing {kib} space. For best results, your image should be 64x64. Images will not be optimized by this API call, so care should be taken when using custom images. `solution`:: - (Optional, string) The solution defined for the space. Can be one of `security`, `observability`, `search`, `classic`. + (Optional, string) The solution defined for the space. Can be one of `security`, `oblt`, `es`, `classic`. [[spaces-api-put-response-codes]] ==== Response codes diff --git a/src/plugins/navigation/public/plugin.test.ts b/src/plugins/navigation/public/plugin.test.ts index 19c104ebe52f2..6ebdfbe5003a2 100644 --- a/src/plugins/navigation/public/plugin.test.ts +++ b/src/plugins/navigation/public/plugin.test.ts @@ -104,7 +104,7 @@ describe('Navigation Plugin', () => { spaces.getActiveSpace$ = jest .fn() - .mockReturnValue(of({ solution: 'search' } as Pick)); + .mockReturnValue(of({ solution: 'es' } as Pick)); plugin.start(coreStart, { unifiedSearch, cloud, cloudExperiments, spaces }); await new Promise((resolve) => setTimeout(resolve)); @@ -201,7 +201,7 @@ describe('Navigation Plugin', () => { featureOn: true, }); - for (const solution of ['search', 'observability', 'security']) { + for (const solution of ['es', 'oblt', 'security']) { spaces.getActiveSpace$ = jest .fn() .mockReturnValue(of({ solution } as Pick)); diff --git a/src/plugins/navigation/public/plugin.tsx b/src/plugins/navigation/public/plugin.tsx index 8c8ca5dec5b83..8aa9eea2351d6 100644 --- a/src/plugins/navigation/public/plugin.tsx +++ b/src/plugins/navigation/public/plugin.tsx @@ -168,8 +168,12 @@ export class NavigationPublicPlugin activeSpace, }: { isFeatureEnabled: boolean; isServerless: boolean; activeSpace?: Space } ) { - const solutionView = serializeSpaceSolution(activeSpace); - const isProjectNav = isFeatureEnabled && Boolean(solutionView) && solutionView !== 'classic'; + const solutionView = activeSpace?.solution; + const isProjectNav = + isFeatureEnabled && + Boolean(solutionView) && + isKnownSolutionView(solutionView) && + solutionView !== 'classic'; // On serverless the chrome style is already set by the serverless plugin if (!isServerless) { @@ -182,10 +186,6 @@ export class NavigationPublicPlugin } } -function serializeSpaceSolution(space?: Space): 'classic' | 'es' | 'oblt' | 'security' | undefined { - if (!space) return undefined; - if (space.solution === 'search') return 'es'; - if (space.solution === 'observability') return 'oblt'; - if (space.solution === 'security') return 'security'; - return undefined; +function isKnownSolutionView(solution?: string) { + return solution && ['oblt', 'es', 'security'].includes(solution); } diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index 791d784c36a0d..cf362926bdd04 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -8,7 +8,7 @@ import type { Subscription } from 'rxjs'; import { map } from 'rxjs'; -import type { CloudStart } from '@kbn/cloud-plugin/server'; +import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/server'; import type { TypeOf } from '@kbn/config-schema'; import type { CoreSetup, @@ -88,6 +88,7 @@ export interface PluginSetupDependencies { taskManager: TaskManagerSetupContract; usageCollection?: UsageCollectionSetup; spaces?: SpacesPluginSetup; + cloud?: CloudSetup; } export interface PluginStartDependencies { diff --git a/x-pack/plugins/spaces/common/types/space/v1.ts b/x-pack/plugins/spaces/common/types/space/v1.ts index e18ad5e656efc..9f110dc3098e3 100644 --- a/x-pack/plugins/spaces/common/types/space/v1.ts +++ b/x-pack/plugins/spaces/common/types/space/v1.ts @@ -5,6 +5,8 @@ * 2.0. */ +import type { OnBoardingDefaultSolution } from '@kbn/cloud-plugin/common'; + /** * A Space. */ @@ -62,7 +64,7 @@ export interface Space { /** * Solution selected for this space. */ - solution?: 'security' | 'observability' | 'search' | 'classic'; + solution?: OnBoardingDefaultSolution | 'classic'; } /** diff --git a/x-pack/plugins/spaces/kibana.jsonc b/x-pack/plugins/spaces/kibana.jsonc index e46747a401ea4..3b1555b52fcfd 100644 --- a/x-pack/plugins/spaces/kibana.jsonc +++ b/x-pack/plugins/spaces/kibana.jsonc @@ -18,7 +18,8 @@ "optionalPlugins": [ "home", "management", - "usageCollection" + "usageCollection", + "cloud" ], "requiredBundles": [ "esUiShared", diff --git a/x-pack/plugins/spaces/server/default_space/create_default_space.test.ts b/x-pack/plugins/spaces/server/default_space/create_default_space.test.ts index e7a7b51b278d1..7a401defe0aad 100644 --- a/x-pack/plugins/spaces/server/default_space/create_default_space.test.ts +++ b/x-pack/plugins/spaces/server/default_space/create_default_space.test.ts @@ -87,6 +87,31 @@ test(`it creates the default space when one does not exist`, async () => { ); }); +test(`it creates the default space when one does not exist with defined solution`, async () => { + const deps = createMockDeps({ + defaultExists: false, + }); + + await createDefaultSpace({ ...deps, solution: 'security' }); + + const repository = (await deps.getSavedObjects()).createInternalRepository(); + + expect(repository.get).toHaveBeenCalledTimes(1); + expect(repository.create).toHaveBeenCalledTimes(1); + expect(repository.create).toHaveBeenCalledWith( + 'space', + { + _reserved: true, + description: 'This is your default space!', + disabledFeatures: [], + name: 'Default', + color: '#00bfb3', + solution: 'security', + }, + { id: 'default' } + ); +}); + test(`it does not attempt to recreate the default space if it already exists`, async () => { const deps = createMockDeps({ defaultExists: true, diff --git a/x-pack/plugins/spaces/server/default_space/create_default_space.ts b/x-pack/plugins/spaces/server/default_space/create_default_space.ts index a7aee5a6d0ea1..53658fd68a0f7 100644 --- a/x-pack/plugins/spaces/server/default_space/create_default_space.ts +++ b/x-pack/plugins/spaces/server/default_space/create_default_space.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { OnBoardingDefaultSolution } from '@kbn/cloud-plugin/common'; import type { Logger, SavedObjectsRepository, SavedObjectsServiceStart } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; @@ -14,9 +15,10 @@ import { DEFAULT_SPACE_ID } from '../../common/constants'; interface Deps { getSavedObjects: () => Promise>; logger: Logger; + solution?: OnBoardingDefaultSolution; } -export async function createDefaultSpace({ getSavedObjects, logger }: Deps) { +export async function createDefaultSpace({ getSavedObjects, logger, solution }: Deps) { const { createInternalRepository } = await getSavedObjects(); const savedObjectsRepository = createInternalRepository(['space']); @@ -48,6 +50,7 @@ export async function createDefaultSpace({ getSavedObjects, logger }: Deps) { color: '#00bfb3', disabledFeatures: [], _reserved: true, + ...(solution ? { solution } : {}), }, options ); diff --git a/x-pack/plugins/spaces/server/default_space/default_space_service.ts b/x-pack/plugins/spaces/server/default_space/default_space_service.ts index d4c601369fde1..1faaf5490de89 100644 --- a/x-pack/plugins/spaces/server/default_space/default_space_service.ts +++ b/x-pack/plugins/spaces/server/default_space/default_space_service.ts @@ -19,6 +19,7 @@ import { timer, } from 'rxjs'; +import type { OnBoardingDefaultSolution } from '@kbn/cloud-plugin/common'; import type { CoreSetup, Logger, SavedObjectsServiceStart, ServiceStatus } from '@kbn/core/server'; import { ServiceStatusLevels } from '@kbn/core/server'; import type { ILicense } from '@kbn/licensing-plugin/server'; @@ -32,6 +33,7 @@ interface Deps { license$: Observable; spacesLicense: SpacesLicense; logger: Logger; + solution?: OnBoardingDefaultSolution; } export const RETRY_SCALE_DURATION = 100; @@ -64,7 +66,7 @@ export class DefaultSpaceService { private serviceStatus$?: BehaviorSubject; - public setup({ coreStatus, getSavedObjects, license$, spacesLicense, logger }: Deps) { + public setup({ coreStatus, getSavedObjects, license$, spacesLicense, logger, solution }: Deps) { const statusLogger = logger.get('status'); this.serviceStatus$ = new BehaviorSubject({ @@ -96,6 +98,7 @@ export class DefaultSpaceService { createDefaultSpace({ getSavedObjects, logger, + solution, }).then(() => { return { level: ServiceStatusLevels.available, diff --git a/x-pack/plugins/spaces/server/lib/space_schema.test.ts b/x-pack/plugins/spaces/server/lib/space_schema.test.ts index c31d7f5ca3c22..59795a6519dec 100644 --- a/x-pack/plugins/spaces/server/lib/space_schema.test.ts +++ b/x-pack/plugins/spaces/server/lib/space_schema.test.ts @@ -238,7 +238,7 @@ describe('#imageUrl', () => { describe('#solution', () => { it('should throw error if solution is defined in serverless offering', () => { expect(() => - spaceServerlessSchema.validate({ ...defaultProperties, solution: 'search' }) + spaceServerlessSchema.validate({ ...defaultProperties, solution: 'es' }) ).toThrow(); }); @@ -253,13 +253,13 @@ describe('#solution', () => { .toThrowErrorMatchingInlineSnapshot(` "[solution]: types that failed validation: - [solution.0]: expected value to equal [security] - - [solution.1]: expected value to equal [observability] - - [solution.2]: expected value to equal [search] + - [solution.1]: expected value to equal [oblt] + - [solution.2]: expected value to equal [es] - [solution.3]: expected value to equal [classic]" `); expect(() => - spaceBaseSchema.validate({ ...defaultProperties, solution: ' search ' }, {}) + spaceBaseSchema.validate({ ...defaultProperties, solution: ' es ' }, {}) ).toThrow(); }); }); diff --git a/x-pack/plugins/spaces/server/lib/space_schema.ts b/x-pack/plugins/spaces/server/lib/space_schema.ts index cb184e322b5a9..f43ca3bc58f53 100644 --- a/x-pack/plugins/spaces/server/lib/space_schema.ts +++ b/x-pack/plugins/spaces/server/lib/space_schema.ts @@ -46,8 +46,8 @@ const spaceSchema = schema.object({ const solutionSchema = schema.oneOf([ schema.literal('security'), - schema.literal('observability'), - schema.literal('search'), + schema.literal('oblt'), + schema.literal('es'), schema.literal('classic'), ]); diff --git a/x-pack/plugins/spaces/server/plugin.test.ts b/x-pack/plugins/spaces/server/plugin.test.ts index 3ac505c6e2e9a..b181b87e9cc94 100644 --- a/x-pack/plugins/spaces/server/plugin.test.ts +++ b/x-pack/plugins/spaces/server/plugin.test.ts @@ -7,15 +7,20 @@ import { lastValueFrom } from 'rxjs'; +import { cloudMock } from '@kbn/cloud-plugin/public/mocks'; +import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { CoreSetup } from '@kbn/core/server'; import { coreMock } from '@kbn/core/server/mocks'; import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/server/mocks'; +import { createDefaultSpace } from './default_space/create_default_space'; import type { PluginsStart } from './plugin'; import { SpacesPlugin } from './plugin'; +jest.mock('./default_space/create_default_space'); + describe('Spaces plugin', () => { describe('#setup', () => { it('can setup with all optional plugins disabled, exposing the expected contract', () => { @@ -76,6 +81,25 @@ describe('Spaces plugin', () => { expect(usageCollection.getCollectorByType('spaces')).toBeDefined(); }); + + it('can setup space with default solution', async () => { + const initializerContext = coreMock.createPluginInitializerContext({ maxSpaces: 1000 }); + const core = coreMock.createSetup() as CoreSetup; + const features = featuresPluginMock.createSetup(); + const licensing = licensingMock.createSetup(); + const cloud = { + ...cloudMock.createSetup(), + apm: {}, + onboarding: { defaultSolution: 'security' }, + } as CloudSetup; + + const plugin = new SpacesPlugin(initializerContext); + plugin.setup(core, { features, licensing, cloud }); + + expect(createDefaultSpace).toHaveBeenCalledWith( + expect.objectContaining({ solution: 'security' }) + ); + }); }); describe('#start', () => { diff --git a/x-pack/plugins/spaces/server/plugin.ts b/x-pack/plugins/spaces/server/plugin.ts index a20396c3e4695..6ca6e27291f7d 100644 --- a/x-pack/plugins/spaces/server/plugin.ts +++ b/x-pack/plugins/spaces/server/plugin.ts @@ -8,6 +8,7 @@ import type { Observable } from 'rxjs'; import { map } from 'rxjs'; +import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { CoreSetup, CoreStart, @@ -46,6 +47,7 @@ export interface PluginsSetup { licensing: LicensingPluginSetup; usageCollection?: UsageCollectionSetup; home?: HomeServerPluginSetup; + cloud?: CloudSetup; } export interface PluginsStart { @@ -161,6 +163,7 @@ export class SpacesPlugin license$: plugins.licensing.license$, spacesLicense: license, logger: this.log, + solution: plugins.cloud?.onboarding?.defaultSolution, }); initSpacesViewsRoutes({ diff --git a/x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts b/x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts index eb038d03e21aa..ffa9ee7a8f574 100644 --- a/x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts +++ b/x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts @@ -46,8 +46,8 @@ export class SpacesSavedObjectsService { solution: schema.maybe( schema.oneOf([ schema.literal('security'), - schema.literal('observability'), - schema.literal('search'), + schema.literal('oblt'), + schema.literal('es'), schema.literal('classic'), ]) ), diff --git a/x-pack/plugins/spaces/server/spaces_client/spaces_client.test.ts b/x-pack/plugins/spaces/server/spaces_client/spaces_client.test.ts index 600f6d1aa316c..d9a23a3bc0c45 100644 --- a/x-pack/plugins/spaces/server/spaces_client/spaces_client.test.ts +++ b/x-pack/plugins/spaces/server/spaces_client/spaces_client.test.ts @@ -42,7 +42,7 @@ describe('#getAll', () => { imageUrl: 'go-bots/predates/transformers', disabledFeatures: [], _reserved: true, - solution: 'search', + solution: 'es', bar: 'foo-bar', // an extra attribute that will be ignored during conversion }, }, @@ -81,7 +81,7 @@ describe('#getAll', () => { initials: 'FB', imageUrl: 'go-bots/predates/transformers', disabledFeatures: [], - solution: 'search', + solution: 'es', _reserved: true, }, { @@ -224,7 +224,7 @@ describe('#get', () => { const mockCallWithRequestRepository = savedObjectsRepositoryMock.create(); mockCallWithRequestRepository.get.mockResolvedValue({ ...savedObject, - attributes: { ...(savedObject.attributes as Record), solution: 'search' }, + attributes: { ...(savedObject.attributes as Record), solution: 'es' }, }); const mockConfig = createMockConfig(); @@ -247,7 +247,7 @@ describe('#get', () => { const mockCallWithRequestRepository = savedObjectsRepositoryMock.create(); mockCallWithRequestRepository.get.mockResolvedValue({ ...savedObject, - attributes: { ...(savedObject.attributes as Record), solution: 'search' }, + attributes: { ...(savedObject.attributes as Record), solution: 'es' }, }); const mockConfig = createMockConfig(); @@ -261,7 +261,7 @@ describe('#get', () => { const id = savedObject.id; const actualSpace = await client.get(id); - expect(actualSpace).toEqual({ ...expectedSpace, solution: 'search' }); + expect(actualSpace).toEqual({ ...expectedSpace, solution: 'es' }); }); }); @@ -399,7 +399,7 @@ describe('#create', () => { ); await expect( - client.create({ ...spaceToCreate, solution: 'search' }) + client.create({ ...spaceToCreate, solution: 'es' }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Unable to create Space, solution property is forbidden in serverless"` ); @@ -418,7 +418,7 @@ describe('#create', () => { const mockCallWithRequestRepository = savedObjectsRepositoryMock.create(); mockCallWithRequestRepository.create.mockResolvedValue({ ...savedObject, - attributes: { ...(savedObject.attributes as Record), solution: 'search' }, + attributes: { ...(savedObject.attributes as Record), solution: 'es' }, }); mockCallWithRequestRepository.find.mockResolvedValue({ total: maxSpaces - 1, @@ -438,9 +438,9 @@ describe('#create', () => { 'traditional' ); - const actualSpace = await client.create({ ...spaceToCreate, solution: 'search' }); + const actualSpace = await client.create({ ...spaceToCreate, solution: 'es' }); - expect(actualSpace).toEqual({ ...expectedReturnedSpace, solution: 'search' }); + expect(actualSpace).toEqual({ ...expectedReturnedSpace, solution: 'es' }); expect(mockCallWithRequestRepository.find).toHaveBeenCalledWith({ type: 'space', @@ -449,7 +449,7 @@ describe('#create', () => { }); expect(mockCallWithRequestRepository.create).toHaveBeenCalledWith( 'space', - { ...attributes, solution: 'search' }, + { ...attributes, solution: 'es' }, { id, } @@ -609,7 +609,7 @@ describe('#update', () => { ); await expect( - client.update(id, { ...spaceToUpdate, solution: 'search' }) + client.update(id, { ...spaceToUpdate, solution: 'es' }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Unable to update Space, solution property is forbidden in serverless"` ); @@ -659,11 +659,11 @@ describe('#update', () => { 'traditional' ); const id = savedObject.id; - await client.update(id, { ...spaceToUpdate, solution: 'search' }); + await client.update(id, { ...spaceToUpdate, solution: 'es' }); expect(mockCallWithRequestRepository.update).toHaveBeenCalledWith('space', id, { ...attributes, - solution: 'search', + solution: 'es', }); expect(mockCallWithRequestRepository.get).toHaveBeenCalledWith('space', id); }); diff --git a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts index 16b5ca1a1e9f0..d222c21fc72be 100644 --- a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts +++ b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts @@ -46,7 +46,7 @@ async function getSpacesUsage( } const knownFeatureIds = features.getKibanaFeatures().map((feature) => feature.id); - const knownSolutions = ['classic', 'search', 'observability', 'security', 'unset']; + const knownSolutions = ['classic', 'es', 'oblt', 'security', 'unset']; const resp = (await esClient.search({ index: kibanaIndex, @@ -205,13 +205,13 @@ export function getSpacesUsageCollector( description: 'The number of spaces which have solution set to classic.', }, }, - search: { + es: { type: 'long', _meta: { description: 'The number of spaces which have solution set to search.', }, }, - observability: { + oblt: { type: 'long', _meta: { description: 'The number of spaces which have solution set to observability.', diff --git a/x-pack/plugins/spaces/tsconfig.json b/x-pack/plugins/spaces/tsconfig.json index 048004ff11334..b0da959cc57ea 100644 --- a/x-pack/plugins/spaces/tsconfig.json +++ b/x-pack/plugins/spaces/tsconfig.json @@ -36,6 +36,7 @@ "@kbn/react-kibana-context-render", "@kbn/utility-types-jest", "@kbn/security-plugin-types-public", + "@kbn/cloud-plugin", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index b63d1f52b37a3..a42825ed281f6 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -15121,13 +15121,13 @@ "description": "The number of spaces which have solution set to classic." } }, - "search": { + "es": { "type": "long", "_meta": { "description": "The number of spaces which have solution set to search." } }, - "observability": { + "oblt": { "type": "long", "_meta": { "description": "The number of spaces which have solution set to observability." diff --git a/x-pack/test/spaces_api_integration/common/suites/create.ts b/x-pack/test/spaces_api_integration/common/suites/create.ts index c7aab659ce960..fc2bd1b841ccc 100644 --- a/x-pack/test/spaces_api_integration/common/suites/create.ts +++ b/x-pack/test/spaces_api_integration/common/suites/create.ts @@ -71,7 +71,7 @@ export function createTestSuiteFactory(esArchiver: any, supertest: SuperTest Date: Tue, 18 Jun 2024 11:35:32 +0200 Subject: [PATCH 037/127] config-schema: implements `intersection` (#186269) ## Summary Fix https://github.com/elastic/kibana/issues/185018 Add a new `schema.intersection` (alias `schema.allOf` for consistency with `schema.oneOf`) API to `@kbn/config-schema`, allowing to create object schema based on the intersection of other object schemas. ```ts const mySchema = schema.intersection([ schema.object({ someKey: schema.string(), }), schema.object({ anotherKey: schema.string(), }) ]); ``` --- packages/kbn-config-schema/README.md | 25 +++ packages/kbn-config-schema/index.ts | 163 ++++++++++++++++++ packages/kbn-config-schema/src/types/index.ts | 10 +- .../src/types/intersection_type.test.ts | 67 +++++++ .../src/types/intersection_type.ts | 31 ++++ .../src/types/object_type.ts | 9 + packages/kbn-config-schema/src/types/type.ts | 6 +- 7 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 packages/kbn-config-schema/src/types/intersection_type.test.ts create mode 100644 packages/kbn-config-schema/src/types/intersection_type.ts diff --git a/packages/kbn-config-schema/README.md b/packages/kbn-config-schema/README.md index 5916f49ef2836..45e46c078baee 100644 --- a/packages/kbn-config-schema/README.md +++ b/packages/kbn-config-schema/README.md @@ -21,6 +21,7 @@ Kibana configuration entries providing developers with a fully typed model of th - [`schema.object()`](#schemaobject) - [`schema.recordOf()`](#schemarecordof) - [`schema.mapOf()`](#schemamapof) + - [`schema.allOf` / `schema.intersection`](#schemaintersection--schemaallof) - [Advanced types](#advanced-types) - [`schema.oneOf()`](#schemaoneof) - [`schema.any()`](#schemaany) @@ -295,6 +296,30 @@ __Notes:__ * You can use a union of literal types as a record's key schema to restrict record to a specific set of keys, e.g. `schema.oneOf([schema.literal('isEnabled'), schema.literal('name')])`. * `schema.mapOf()` also supports a json string as input if it can be safely parsed using `JSON.parse` and if the resulting value is a plain object. +#### `schema.intersection()` / `schema.allOf()` + +Creates an `object` schema being the intersection of the provided `object` schemas. +Note that schema construction will throw an error if some of the intersection schema share the same key(s). + +See the documentation for [schema.object](#schemaobject). + +__Options:__ +* `defaultValue: TObject | Reference | (() => TObject)` - defines a default value, see [Default values](#default-values) section for more details. +* `validate: (value: TObject) => string | void` - defines a custom validator function, see [Custom validation](#custom-validation) section for more details. +* `unknowns: 'allow' | 'ignore' | 'forbid'` - indicates whether unknown object properties should be allowed, ignored, or forbidden. It's `forbid` by default. + +__Usage:__ +```typescript +const mySchema = schema.intersection([ + schema.object({ + someKey: schema.string(), + }), + schema.object({ + anotherKey: schema.string(), + }) +]); +``` + ### Advanced types #### `schema.oneOf()` diff --git a/packages/kbn-config-schema/index.ts b/packages/kbn-config-schema/index.ts index c6ef8c2ce99dc..8195631606381 100644 --- a/packages/kbn-config-schema/index.ts +++ b/packages/kbn-config-schema/index.ts @@ -23,6 +23,8 @@ import { ConditionalTypeValue, DurationOptions, DurationType, + IntersectionType, + IntersectionTypeOptions, IpOptions, IpType, LiteralType, @@ -34,6 +36,7 @@ import { NumberType, ObjectType, ObjectTypeOptions, + ObjectResultType, Props, NullableProps, RecordOfOptions, @@ -199,6 +202,164 @@ function oneOf>>( return new UnionType(types, options); } +function allOf< + A extends Props, + B extends Props, + C extends Props, + D extends Props, + E extends Props, + F extends Props, + G extends Props, + H extends Props, + I extends Props, + J extends Props, + K extends Props +>( + types: [ + ObjectType, + ObjectType
, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType + ], + options?: UnionTypeOptions +): Type>; +function allOf< + A extends Props, + B extends Props, + C extends Props, + D extends Props, + E extends Props, + F extends Props, + G extends Props, + H extends Props, + I extends Props, + J extends Props +>( + types: [ + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType + ], + options?: UnionTypeOptions +): Type>; +function allOf< + A extends Props, + B extends Props, + C extends Props, + D extends Props, + E extends Props, + F extends Props, + G extends Props, + H extends Props, + I extends Props +>( + types: [ + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType + ], + options?: UnionTypeOptions +): Type>; +function allOf< + A extends Props, + B extends Props, + C extends Props, + D extends Props, + E extends Props, + F extends Props, + G extends Props, + H extends Props +>( + types: [ + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType + ], + options?: UnionTypeOptions +): Type>; +function allOf< + A extends Props, + B extends Props, + C extends Props, + D extends Props, + E extends Props, + F extends Props, + G extends Props +>( + types: [ + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType, + ObjectType + ], + options?: UnionTypeOptions +): Type>; +function allOf< + A extends Props, + B extends Props, + C extends Props, + D extends Props, + E extends Props, + F extends Props +>( + types: [ObjectType, ObjectType, ObjectType, ObjectType, ObjectType, ObjectType], + options?: UnionTypeOptions +): Type>; +function allOf( + types: [ObjectType, ObjectType, ObjectType, ObjectType, ObjectType], + options?: UnionTypeOptions +): Type>; +function allOf( + types: [ObjectType, ObjectType, ObjectType, ObjectType], + options?: UnionTypeOptions +): Type>; +function allOf( + types: [ObjectType, ObjectType, ObjectType], + options?: UnionTypeOptions +): Type>; +function allOf( + types: [ObjectType, ObjectType], + options?: UnionTypeOptions +): Type>; +function allOf( + types: [ObjectType], + options?: UnionTypeOptions +): Type>; +function allOf>>( + types: RTS, + options?: IntersectionTypeOptions +): Type { + return new IntersectionType(types, options); +} + function contextRef(key: string): ContextReference { return new ContextReference(key); } @@ -225,6 +386,7 @@ function lazy(id: string) { } export const schema = { + allOf, any, arrayOf, boolean, @@ -233,6 +395,7 @@ export const schema = { conditional, contextRef, duration, + intersection: allOf, ip, lazy, literal, diff --git a/packages/kbn-config-schema/src/types/index.ts b/packages/kbn-config-schema/src/types/index.ts index 78eab0957557d..4c92bb6d078dc 100644 --- a/packages/kbn-config-schema/src/types/index.ts +++ b/packages/kbn-config-schema/src/types/index.ts @@ -20,13 +20,21 @@ export type { ConditionalTypeValue } from './conditional_type'; export { ConditionalType } from './conditional_type'; export type { DurationOptions } from './duration_type'; export { DurationType } from './duration_type'; +export type { IntersectionTypeOptions } from './intersection_type'; +export { IntersectionType } from './intersection_type'; export { LiteralType } from './literal_type'; export { MaybeType } from './maybe_type'; export type { MapOfOptions } from './map_type'; export { MapOfType } from './map_type'; export type { NumberOptions } from './number_type'; export { NumberType } from './number_type'; -export type { ObjectTypeOptions, Props, NullableProps, TypeOf } from './object_type'; +export type { + ObjectTypeOptions, + Props, + NullableProps, + TypeOf, + ObjectResultType, +} from './object_type'; export { ObjectType } from './object_type'; export type { RecordOfOptions } from './record_type'; export { RecordOfType } from './record_type'; diff --git a/packages/kbn-config-schema/src/types/intersection_type.test.ts b/packages/kbn-config-schema/src/types/intersection_type.test.ts new file mode 100644 index 0000000000000..cf1262da0550b --- /dev/null +++ b/packages/kbn-config-schema/src/types/intersection_type.test.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { schema, TypeOf } from '../..'; + +describe('schema.allOf', () => { + it('validates all parts of the intersection', () => { + const type = schema.allOf([ + schema.object({ foo: schema.string() }), + schema.object({ bar: schema.string() }), + ]); + + expect(type.validate({ foo: 'hello', bar: 'dolly' })).toEqual({ foo: 'hello', bar: 'dolly' }); + }); + + it('throw error when one part of the intersection is not matched with the correct error message', () => { + const type = schema.allOf([ + schema.object({ foo: schema.string() }), + schema.object({ bar: schema.string() }), + ]); + + expect(() => type.validate({ foo: 'something' })).toThrowErrorMatchingInlineSnapshot( + `"[bar]: expected value of type [string] but got [undefined]"` + ); + }); + + it('supports default value', () => { + const type = schema.allOf([ + schema.object({ foo: schema.string() }), + schema.object({ bar: schema.string({ defaultValue: 'default' }) }), + ]); + + expect(type.validate({ foo: 'hello' })).toEqual({ foo: 'hello', bar: 'default' }); + }); + + it('throw error if multiple schemas define the same key', () => { + expect(() => + schema.allOf([ + schema.object({ foo: schema.string() }), + schema.object({ foo: schema.literal('bar') }), + ]) + ).toThrowErrorMatchingInlineSnapshot(`"Duplicate key found in intersection: 'foo'"`); + }); + + it('has the right type inference', () => { + const resultingSchema = schema.object({ + foo: schema.string(), + bar: schema.string(), + }); + type ResultingType = TypeOf; + + const type = schema.allOf([ + schema.object({ foo: schema.string() }), + schema.object({ bar: schema.string() }), + ]); + + // asserting the type is the expected one + const output: ResultingType = type.validate({ foo: 'hello', bar: 'dolly' }); + // required to make TS happy + expect(output).toEqual({ foo: 'hello', bar: 'dolly' }); + }); +}); diff --git a/packages/kbn-config-schema/src/types/intersection_type.ts b/packages/kbn-config-schema/src/types/intersection_type.ts new file mode 100644 index 0000000000000..766a0786103fc --- /dev/null +++ b/packages/kbn-config-schema/src/types/intersection_type.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ObjectType, Props, ObjectTypeOptions } from './object_type'; + +export type IntersectionTypeOptions = ObjectTypeOptions; + +export class IntersectionType< + RTS extends Array>, + T extends Props +> extends ObjectType { + constructor(types: RTS, options?: IntersectionTypeOptions) { + const props = types.reduce((mergedProps, type) => { + Object.entries(type.getPropSchemas() as Record).forEach(([key, value]) => { + if (mergedProps[key] !== undefined) { + throw new Error(`Duplicate key found in intersection: '${key}'`); + } + mergedProps[key as keyof T] = value; + }); + + return mergedProps; + }, {} as T); + + super(props, options); + } +} diff --git a/packages/kbn-config-schema/src/types/object_type.ts b/packages/kbn-config-schema/src/types/object_type.ts index d5193b5e0fc38..423d6030b30b0 100644 --- a/packages/kbn-config-schema/src/types/object_type.ts +++ b/packages/kbn-config-schema/src/types/object_type.ts @@ -223,6 +223,15 @@ export class ObjectType

extends Type> } } + /** + * Return the schema for this object's underlying properties + * + * @internal should only be used internal for type reflection + */ + public getPropSchemas(): P { + return this.props; + } + validateKey(key: string, value: any) { if (!this.propSchemas[key]) { throw new Error(`${key} is not a valid part of this schema`); diff --git a/packages/kbn-config-schema/src/types/type.ts b/packages/kbn-config-schema/src/types/type.ts index 652eae077d5af..3b8808dba61af 100644 --- a/packages/kbn-config-schema/src/types/type.ts +++ b/packages/kbn-config-schema/src/types/type.ts @@ -125,7 +125,11 @@ export abstract class Type { return this; } - public validate(value: any, context: Record = {}, namespace?: string): V { + /** + * Validates the provided value against this schema. + * If valid, the resulting output will be returned, otherwise an exception will be thrown. + */ + public validate(value: unknown, context: Record = {}, namespace?: string): V { const { value: validatedValue, error } = this.internalSchema.validate(value, { context, presence: 'required', From cf67fede6e0ac1b45210bd5300f8c099a855ea6f Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 18 Jun 2024 11:42:45 +0200 Subject: [PATCH 038/127] [Defend Workflows] Skip Cypress tests on MKI executions (#186120) ## Summary The `x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts` test is failing on MKI environments (the periodic pipeline). This is because the test in order to work need to have a feature flag enabled. FF are not currently supported on MKI environments, that is why in this PR we are skipping it from MKI environments by adding `@skipInServerlessMKI` label to it. Co-authored-by: Ash <1849116+ashokaditya@users.noreply.github.com> --- .../cypress/e2e/response_actions/response_console/scan.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts index f05e0581332cf..59c6916f23fff 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts @@ -33,7 +33,7 @@ describe( ], }, }, - tags: ['@ess', '@serverless'], + tags: ['@ess', '@serverless', '@skipInServerlessMKI'], }, () => { beforeEach(() => { From 3a2e1621f423613b62eb299d7c21fa61d6138bed Mon Sep 17 00:00:00 2001 From: Antonio Date: Tue, 18 Jun 2024 11:45:41 +0200 Subject: [PATCH 039/127] [ResponseOps][Connectors] SSL for Cases Webhook (#185925) Fixes #180255 ## Summary Adds API support and UI for CA and client-side SSL certificate authentication to the Cases webhook connector. aux This PR is to merge a feature branch into `main`. This feature branch is composed of the following PRs: - https://github.com/elastic/kibana/pull/183711 - https://github.com/elastic/kibana/pull/183919 - https://github.com/elastic/kibana/pull/184313 ### How to test @cnasikas kindly provided a node server that can be setup locally to test the certificates against. Ping me offline and i will send you the rar. You will need to configure a connector of type `Cases Webhook connector`. #### Configuring `Authentication`: The project folder has two sets of keys, one for Alice and one for Bob. The Alice keys should work and the Bob keys are expected to be unauthorized. - For `CRT and KEY File` use: - `alice_cert.pem` and `alice_key.pem` respectively (or `bob_*`) - For `PFX File` use: - `alice.p12` or `bob.p12`. - Toggle `Add certificate authority`. - Select `Verification mode` to be `none`. #### Configuring `Create case`: Only the URL is relevant. It should be `https://localhost:9999/authenticate`. Everything else can have whatever values you want. ### Release Notes The Cases webhook connector now supports SSL certificate authentication. --- .../connector_types.test.ts.snap | 288 ++++++- .../common/{webhook => auth}/constants.ts | 8 +- .../webhook => common/auth}/mocks.ts | 0 .../stack_connectors/common/auth/schema.ts | 61 ++ .../stack_connectors/common/auth/types.ts | 20 + .../common/auth/utils.test.ts | 209 +++++ .../stack_connectors/common/auth/utils.ts | 101 +++ .../public/common/auth/auth_config.test.tsx | 483 +++++++++++ .../public/common/auth/auth_config.tsx | 292 +++++++ .../common/auth/basic_auth_fields.test.tsx | 112 +++ .../public/common/auth/basic_auth_fields.tsx | 60 ++ .../common/auth/ssl_cert_fields.test.tsx | 223 +++++ .../public/common/auth/ssl_cert_fields.tsx | 138 +++ .../public/common/auth/translations.ts | 159 ++++ .../cases_webhook/steps/auth.tsx | 175 +--- .../cases_webhook/translations.ts | 78 -- .../cases_webhook/webhook_connectors.test.tsx | 459 +++++----- .../public/connector_types/lib/test_utils.tsx | 15 + .../connector_types/webhook/translations.ts | 159 ---- .../webhook/webhook_connectors.test.tsx | 24 +- .../webhook/webhook_connectors.tsx | 407 +-------- .../connector_types/cases_webhook/index.ts | 8 +- .../connector_types/cases_webhook/schema.ts | 43 +- .../cases_webhook/service.test.ts | 788 ++++++++++++++++-- .../connector_types/cases_webhook/service.ts | 52 +- .../cases_webhook/translations.ts | 9 +- .../connector_types/cases_webhook/types.ts | 23 - .../cases_webhook/validators.ts | 31 +- .../server/connector_types/index.ts | 2 +- .../server/connector_types/lib/nullable.ts | 14 - .../connector_types/webhook/index.test.ts | 30 +- .../server/connector_types/webhook/index.ts | 132 +-- .../server/connector_types/webhook/schema.ts | 32 + .../server/connector_types/webhook/types.ts | 34 + .../plugins/stack_connectors/server/index.ts | 2 +- .../translations/translations/fr-FR.json | 37 - .../translations/translations/ja-JP.json | 37 - .../translations/translations/zh-CN.json | 37 - .../actions/connector_types/cases_webhook.ts | 2 +- .../perform_bulk_action.ts | 4 +- 40 files changed, 3324 insertions(+), 1464 deletions(-) rename x-pack/plugins/stack_connectors/common/{webhook => auth}/constants.ts (79%) rename x-pack/plugins/stack_connectors/{server/connector_types/webhook => common/auth}/mocks.ts (100%) create mode 100644 x-pack/plugins/stack_connectors/common/auth/schema.ts create mode 100644 x-pack/plugins/stack_connectors/common/auth/types.ts create mode 100644 x-pack/plugins/stack_connectors/common/auth/utils.test.ts create mode 100644 x-pack/plugins/stack_connectors/common/auth/utils.ts create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/auth_config.test.tsx create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/auth_config.tsx create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.test.tsx create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.tsx create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.test.tsx create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.tsx create mode 100644 x-pack/plugins/stack_connectors/public/common/auth/translations.ts delete mode 100644 x-pack/plugins/stack_connectors/server/connector_types/lib/nullable.ts create mode 100644 x-pack/plugins/stack_connectors/server/connector_types/webhook/schema.ts create mode 100644 x-pack/plugins/stack_connectors/server/connector_types/webhook/types.ts diff --git a/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap b/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap index 84f1c1966747b..c9c525272a391 100644 --- a/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap +++ b/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap @@ -1139,6 +1139,117 @@ Object { "presence": "optional", }, "keys": Object { + "authType": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "allow": Array [ + "webhook-authentication-basic", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "webhook-authentication-ssl", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + null, + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "alternatives", + }, + "ca": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + "certType": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "allow": Array [ + "ssl-crt-key", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "ssl-pfx", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "alternatives", + }, "createCommentJson": Object { "flags": Object { "default": null, @@ -1399,7 +1510,7 @@ Object { }, "headers": Object { "flags": Object { - "default": [Function], + "default": null, "error": [Function], "presence": "optional", }, @@ -1541,6 +1652,57 @@ Object { ], "type": "string", }, + "verificationMode": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "allow": Array [ + "none", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "certificate", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "full", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "alternatives", + }, "viewIncidentUrl": Object { "flags": Object { "error": [Function], @@ -1575,6 +1737,82 @@ Object { "presence": "optional", }, "keys": Object { + "crt": Object { + "flags": Object { + "default": null, + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "flags": Object { + "error": [Function], + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + }, + Object { + "schema": Object { + "allow": Array [ + null, + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "type": "alternatives", + }, + "key": Object { + "flags": Object { + "default": null, + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "flags": Object { + "error": [Function], + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + }, + Object { + "schema": Object { + "allow": Array [ + null, + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "type": "alternatives", + }, "password": Object { "flags": Object { "default": null, @@ -1613,6 +1851,44 @@ Object { ], "type": "alternatives", }, + "pfx": Object { + "flags": Object { + "default": null, + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "flags": Object { + "error": [Function], + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + }, + Object { + "schema": Object { + "allow": Array [ + null, + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "type": "alternatives", + }, "user": Object { "flags": Object { "default": null, @@ -1657,6 +1933,14 @@ Object { "objects": false, }, }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], "type": "object", } `; @@ -32515,7 +32799,7 @@ Object { }, "headers": Object { "flags": Object { - "default": [Function], + "default": null, "error": [Function], "presence": "optional", }, diff --git a/x-pack/plugins/stack_connectors/common/webhook/constants.ts b/x-pack/plugins/stack_connectors/common/auth/constants.ts similarity index 79% rename from x-pack/plugins/stack_connectors/common/webhook/constants.ts rename to x-pack/plugins/stack_connectors/common/auth/constants.ts index 48134762b34db..bdd5b7352f921 100644 --- a/x-pack/plugins/stack_connectors/common/webhook/constants.ts +++ b/x-pack/plugins/stack_connectors/common/auth/constants.ts @@ -5,7 +5,7 @@ * 2.0. */ -export enum WebhookAuthType { +export enum AuthType { Basic = 'webhook-authentication-basic', SSL = 'webhook-authentication-ssl', } @@ -14,3 +14,9 @@ export enum SSLCertType { CRT = 'ssl-crt-key', PFX = 'ssl-pfx', } + +export enum WebhookMethods { + PATCH = 'patch', + POST = 'post', + PUT = 'put', +} diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/mocks.ts b/x-pack/plugins/stack_connectors/common/auth/mocks.ts similarity index 100% rename from x-pack/plugins/stack_connectors/server/connector_types/webhook/mocks.ts rename to x-pack/plugins/stack_connectors/common/auth/mocks.ts diff --git a/x-pack/plugins/stack_connectors/common/auth/schema.ts b/x-pack/plugins/stack_connectors/common/auth/schema.ts new file mode 100644 index 0000000000000..91754b38f84db --- /dev/null +++ b/x-pack/plugins/stack_connectors/common/auth/schema.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +import { schema } from '@kbn/config-schema'; +import { AuthType, SSLCertType } from './constants'; + +export const authTypeSchema = schema.maybe( + schema.oneOf( + [schema.literal(AuthType.Basic), schema.literal(AuthType.SSL), schema.literal(null)], + { + defaultValue: AuthType.Basic, + } + ) +); + +export const hasAuthSchema = schema.boolean({ defaultValue: true }); + +export const AuthConfiguration = { + hasAuth: hasAuthSchema, + authType: authTypeSchema, + certType: schema.maybe( + schema.oneOf([schema.literal(SSLCertType.CRT), schema.literal(SSLCertType.PFX)]) + ), + ca: schema.maybe(schema.string()), + verificationMode: schema.maybe( + schema.oneOf([schema.literal('none'), schema.literal('certificate'), schema.literal('full')]) + ), +}; + +export const SecretConfiguration = { + user: schema.nullable(schema.string()), + password: schema.nullable(schema.string()), + crt: schema.nullable(schema.string()), + key: schema.nullable(schema.string()), + pfx: schema.nullable(schema.string()), +}; + +export const SecretConfigurationSchemaValidation = { + validate: (secrets: any) => { + // user and password must be set together (or not at all) + if (!secrets.password && !secrets.user && !secrets.crt && !secrets.key && !secrets.pfx) return; + if (secrets.password && secrets.user && !secrets.crt && !secrets.key && !secrets.pfx) return; + if (secrets.crt && secrets.key && !secrets.user && !secrets.pfx) return; + if (!secrets.crt && !secrets.key && !secrets.user && secrets.pfx) return; + return i18n.translate('xpack.stackConnectors.webhook.invalidSecrets', { + defaultMessage: + 'must specify one of the following schemas: user and password; crt and key (with optional password); or pfx (with optional password)', + }); + }, +}; + +export const SecretConfigurationSchema = schema.object( + SecretConfiguration, + SecretConfigurationSchemaValidation +); diff --git a/x-pack/plugins/stack_connectors/common/auth/types.ts b/x-pack/plugins/stack_connectors/common/auth/types.ts new file mode 100644 index 0000000000000..ba09bc1a23d68 --- /dev/null +++ b/x-pack/plugins/stack_connectors/common/auth/types.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TypeOf } from '@kbn/config-schema'; +import { + AuthConfiguration, + authTypeSchema, + hasAuthSchema, + SecretConfigurationSchema, +} from './schema'; + +export type HasAuth = TypeOf; +export type AuthTypeName = TypeOf; +export type SecretsConfigurationType = TypeOf; +export type CAType = TypeOf; +export type VerificationModeType = TypeOf; diff --git a/x-pack/plugins/stack_connectors/common/auth/utils.test.ts b/x-pack/plugins/stack_connectors/common/auth/utils.test.ts new file mode 100644 index 0000000000000..78209d0d1db7b --- /dev/null +++ b/x-pack/plugins/stack_connectors/common/auth/utils.test.ts @@ -0,0 +1,209 @@ +/* + * Copyright 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 { AuthType } from './constants'; +import { buildConnectorAuth, isBasicAuth, validateConnectorAuthConfiguration } from './utils'; + +describe('utils', () => { + describe('isBasicAuth', () => { + it('returns false when hasAuth is false and authType is undefined', () => { + expect( + isBasicAuth({ + hasAuth: false, + authType: undefined, + }) + ).toBe(false); + }); + + it('returns false when hasAuth is false and authType is basic', () => { + expect( + isBasicAuth({ + hasAuth: false, + authType: AuthType.Basic, + }) + ).toBe(false); + }); + + it('returns false when hasAuth is true and authType is ssl', () => { + expect( + isBasicAuth({ + hasAuth: true, + authType: AuthType.SSL, + }) + ).toBe(false); + }); + + it('returns true when hasAuth is true and authType is undefined', () => { + expect( + isBasicAuth({ + hasAuth: true, + authType: undefined, + }) + ).toBe(true); + }); + + it('returns true when hasAuth is true and authType is basic', () => { + expect( + isBasicAuth({ + hasAuth: true, + authType: AuthType.Basic, + }) + ).toBe(true); + }); + }); + + describe('validateConnectorAuthConfiguration', () => { + it('does not throw with correct authType=basic params', () => { + expect(() => + validateConnectorAuthConfiguration({ + hasAuth: true, + authType: AuthType.Basic, + basicAuth: { auth: { username: 'foo', password: 'bar' } }, + sslOverrides: {}, + connectorName: 'foobar', + }) + ).not.toThrow(); + }); + + it('does not throw with correct authType=undefined params', () => { + expect(() => + validateConnectorAuthConfiguration({ + hasAuth: true, + authType: undefined, + basicAuth: { auth: { username: 'foo', password: 'bar' } }, + sslOverrides: {}, + connectorName: 'foobar', + }) + ).not.toThrow(); + }); + + it('throws when type is basic and the username is missing', () => { + expect(() => + validateConnectorAuthConfiguration({ + hasAuth: true, + authType: undefined, + // @ts-ignore: that's what we are testing + basicAuth: { auth: { password: 'bar' } }, + sslOverrides: {}, + connectorName: 'Foobar', + }) + ).toThrow('[Action]Foobar: Wrong configuration.'); + }); + + it('throws when type is basic and the password is missing', () => { + expect(() => + validateConnectorAuthConfiguration({ + hasAuth: true, + authType: undefined, + // @ts-ignore: that's what we are testing + basicAuth: { auth: { username: 'foo' } }, + sslOverrides: {}, + connectorName: 'Foobar', + }) + ).toThrow('[Action]Foobar: Wrong configuration.'); + }); + + it('does not throw with correct authType=ssl params', () => { + expect(() => + validateConnectorAuthConfiguration({ + hasAuth: true, + authType: AuthType.SSL, + basicAuth: {}, + sslOverrides: { verificationMode: 'none', passphrase: 'passphrase' }, + connectorName: 'foobar', + }) + ).not.toThrow(); + }); + + it('throws when type is SSL and the sslOverrides are missing', () => { + expect(() => + validateConnectorAuthConfiguration({ + hasAuth: true, + authType: AuthType.SSL, + basicAuth: {}, + sslOverrides: {}, + connectorName: 'Foobar', + }) + ).toThrow('[Action]Foobar: Wrong configuration.'); + }); + }); + + describe('buildConnectorAuth', () => { + it('returns empty objects when hasAuth=false', () => { + expect( + buildConnectorAuth({ + hasAuth: false, + authType: AuthType.SSL, + secrets: { user: 'foo', password: 'bar', crt: null, key: null, pfx: null }, + verificationMode: undefined, + ca: undefined, + }) + ).toEqual({ basicAuth: {}, sslOverrides: {} }); + }); + + it('builds basicAuth correctly with authType=basic', () => { + expect( + buildConnectorAuth({ + hasAuth: true, + authType: AuthType.Basic, + secrets: { user: 'foo', password: 'bar', crt: null, key: null, pfx: null }, + verificationMode: undefined, + ca: undefined, + }) + ).toEqual({ basicAuth: { auth: { username: 'foo', password: 'bar' } }, sslOverrides: {} }); + }); + + it('builds basicAuth correctly with hasAuth=true and authType=undefined', () => { + expect( + buildConnectorAuth({ + hasAuth: true, + authType: undefined, + secrets: { user: 'foo', password: 'bar', crt: null, key: null, pfx: null }, + verificationMode: undefined, + ca: undefined, + }) + ).toEqual({ basicAuth: { auth: { username: 'foo', password: 'bar' } }, sslOverrides: {} }); + }); + + it('builds sslOverrides correctly with authType=ssl', () => { + expect( + buildConnectorAuth({ + hasAuth: true, + authType: AuthType.SSL, + secrets: { user: 'foo', password: 'bar', crt: 'null', key: 'null', pfx: 'null' }, + verificationMode: 'certificate', + ca: 'foobar?', + }) + ).toMatchInlineSnapshot(` + Object { + "basicAuth": Object {}, + "sslOverrides": Object { + "ca": Object { + "data": Array [ + 126, + 138, + 27, + 106, + ], + "type": "Buffer", + }, + "passphrase": "bar", + "pfx": Object { + "data": Array [ + 158, + 233, + 101, + ], + "type": "Buffer", + }, + "verificationMode": "certificate", + }, + } + `); + }); + }); +}); diff --git a/x-pack/plugins/stack_connectors/common/auth/utils.ts b/x-pack/plugins/stack_connectors/common/auth/utils.ts new file mode 100644 index 0000000000000..8c16ee3316274 --- /dev/null +++ b/x-pack/plugins/stack_connectors/common/auth/utils.ts @@ -0,0 +1,101 @@ +/* + * Copyright 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 { isString, isEmpty } from 'lodash'; + +import type { SSLSettings } from '@kbn/actions-plugin/server/types'; +import type { + AuthTypeName, + CAType, + HasAuth, + SecretsConfigurationType, + VerificationModeType, +} from './types'; + +import { AuthType } from './constants'; + +// For backwards compatibility with connectors created before authType was added, interpret a +// hasAuth: true and undefined authType as basic auth +export const isBasicAuth = ({ + hasAuth, + authType, +}: { + hasAuth: HasAuth; + authType: AuthTypeName; +}): boolean => hasAuth && (authType === AuthType.Basic || !authType); + +interface BasicAuthResponse { + auth?: { username: string; password: string }; +} + +export const buildConnectorAuth = ({ + hasAuth, + authType, + secrets, + verificationMode, + ca, +}: { + hasAuth: HasAuth; + authType: AuthTypeName; + secrets: SecretsConfigurationType; + verificationMode: VerificationModeType; + ca: CAType; +}): { basicAuth: BasicAuthResponse; sslOverrides: SSLSettings } => { + let basicAuth: BasicAuthResponse = {}; + let sslOverrides: SSLSettings = {}; + let sslCertificate = {}; + + if (isBasicAuth({ hasAuth, authType })) { + basicAuth = + isString(secrets.user) && isString(secrets.password) + ? { auth: { username: secrets.user, password: secrets.password } } + : {}; + } else if (hasAuth && authType === AuthType.SSL) { + sslCertificate = + (isString(secrets.crt) && isString(secrets.key)) || isString(secrets.pfx) + ? isString(secrets.pfx) + ? { + pfx: Buffer.from(secrets.pfx, 'base64'), + ...(isString(secrets.password) ? { passphrase: secrets.password } : {}), + } + : { + cert: Buffer.from(secrets.crt!, 'base64'), + key: Buffer.from(secrets.key!, 'base64'), + ...(isString(secrets.password) ? { passphrase: secrets.password } : {}), + } + : {}; + } + + sslOverrides = { + ...sslCertificate, + ...(verificationMode ? { verificationMode } : {}), + ...(ca ? { ca: Buffer.from(ca, 'base64') } : {}), + }; + + return { basicAuth, sslOverrides }; +}; + +export const validateConnectorAuthConfiguration = ({ + hasAuth, + authType, + basicAuth, + sslOverrides, + connectorName, +}: { + hasAuth: HasAuth; + authType: AuthTypeName; + basicAuth: BasicAuthResponse; + sslOverrides: SSLSettings; + connectorName: string; +}) => { + if ( + (isBasicAuth({ hasAuth, authType }) && + (!basicAuth.auth?.password || !basicAuth.auth?.username)) || + (authType === AuthType.SSL && isEmpty(sslOverrides)) + ) { + throw Error(`[Action]${connectorName}: Wrong configuration.`); + } +}; diff --git a/x-pack/plugins/stack_connectors/public/common/auth/auth_config.test.tsx b/x-pack/plugins/stack_connectors/public/common/auth/auth_config.test.tsx new file mode 100644 index 0000000000000..6a6e15ac378de --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/auth_config.test.tsx @@ -0,0 +1,483 @@ +/* + * Copyright 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 { AuthConfig } from './auth_config'; +import { render, screen, waitFor, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { AuthType, SSLCertType } from '../../../common/auth/constants'; +import { AuthFormTestProvider } from '../../connector_types/lib/test_utils'; + +describe('AuthConfig renders', () => { + const onSubmit = jest.fn(); + + it('renders all fields for authType=None', async () => { + const testFormData = { + config: { + hasAuth: false, + }, + __internal__: { + hasCA: true, + hasHeaders: true, + }, + }; + render( + + + + ); + + expect(await screen.findByTestId('webhookViewHeadersSwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeaderText')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeadersKeyInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeadersValueInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookAddHeaderButton')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookViewCASwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCAInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookVerificationModeSelect')).toBeInTheDocument(); + expect(await screen.findByTestId('authNone')).toBeInTheDocument(); + expect(await screen.findByTestId('authBasic')).toBeInTheDocument(); + expect(screen.queryByTestId('basicAuthFields')).not.toBeInTheDocument(); + expect(await screen.findByTestId('authSSL')).toBeInTheDocument(); + expect(screen.queryByTestId('sslCertFields')).not.toBeInTheDocument(); + }); + + it('toggles headers as expected', async () => { + const testFormData = { + config: { + hasAuth: false, + }, + __internal__: { + hasCA: false, + hasHeaders: false, + }, + }; + render( + + + + ); + + const headersToggle = await screen.findByTestId('webhookViewHeadersSwitch'); + + expect(headersToggle).toBeInTheDocument(); + + userEvent.click(headersToggle); + + expect(await screen.findByTestId('webhookHeaderText')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeadersKeyInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeadersValueInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookAddHeaderButton')).toBeInTheDocument(); + }); + + it('toggles CA as expected', async () => { + const testFormData = { + config: { + hasAuth: false, + }, + __internal__: { + hasCA: false, + hasHeaders: false, + }, + }; + + render( + + + + ); + + const caToggle = await screen.findByTestId('webhookViewCASwitch'); + + expect(caToggle).toBeInTheDocument(); + + userEvent.click(caToggle); + + expect(await screen.findByTestId('webhookViewCASwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCAInput')).toBeInTheDocument(); + + const verificationModeSelect = await screen.findByTestId('webhookVerificationModeSelect'); + + expect(verificationModeSelect).toBeInTheDocument(); + + ['None', 'Certificate', 'Full'].forEach((optionName) => { + const select = within(verificationModeSelect); + + expect(select.getByRole('option', { name: optionName })); + }); + }); + + it('renders all fields for authType=Basic', async () => { + const testFormData = { + config: { + hasAuth: true, + authType: AuthType.Basic, + }, + secrets: { + user: 'user', + password: 'pass', + }, + }; + + render( + + + + ); + + expect(await screen.findByTestId('webhookViewHeadersSwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookViewCASwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('authNone')).toBeInTheDocument(); + expect(await screen.findByTestId('authBasic')).toBeInTheDocument(); + expect(await screen.findByTestId('basicAuthFields')).toBeInTheDocument(); + expect(await screen.findByTestId('authSSL')).toBeInTheDocument(); + expect(screen.queryByTestId('sslCertFields')).not.toBeInTheDocument(); + }); + + it('renders all fields for authType=SSL', async () => { + const testFormData = { + config: { + hasAuth: true, + authType: AuthType.SSL, + certType: SSLCertType.CRT, + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + key: Buffer.from('some binary string').toString('base64'), + }, + }; + render( + + + + ); + + expect(await screen.findByTestId('webhookViewHeadersSwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookViewCASwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('authNone')).toBeInTheDocument(); + expect(await screen.findByTestId('authBasic')).toBeInTheDocument(); + expect(screen.queryByTestId('basicAuthFields')).not.toBeInTheDocument(); + expect(await screen.findByTestId('authSSL')).toBeInTheDocument(); + expect(await screen.findByTestId('sslCertFields')).toBeInTheDocument(); + }); + + it('renders all fields for authType=SSL and certType=PFX', async () => { + const testFormData = { + config: { + hasAuth: true, + authType: AuthType.SSL, + certType: SSLCertType.PFX, + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + key: Buffer.from('some binary string').toString('base64'), + }, + }; + render( + + + + ); + + expect(await screen.findByTestId('webhookViewHeadersSwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookViewCASwitch')).toBeInTheDocument(); + expect(await screen.findByTestId('authNone')).toBeInTheDocument(); + expect(await screen.findByTestId('authBasic')).toBeInTheDocument(); + expect(screen.queryByTestId('basicAuthFields')).not.toBeInTheDocument(); + expect(await screen.findByTestId('authSSL')).toBeInTheDocument(); + expect(await screen.findByTestId('sslCertFields')).toBeInTheDocument(); + }); + + describe('Validation', () => { + const defaultTestFormData = { + config: { + headers: [{ key: 'content-type', value: 'text' }], + hasAuth: true, + }, + secrets: { + user: 'user', + password: 'pass', + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('succeeds with hasAuth=True', async () => { + const testFormData = { + config: { + headers: [{ key: 'content-type', value: 'text' }], + hasAuth: true, + }, + secrets: { + user: 'user', + password: 'pass', + }, + }; + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + headers: [{ key: 'content-type', value: 'text' }], + hasAuth: true, + authType: AuthType.Basic, + }, + secrets: { + user: 'user', + password: 'pass', + }, + __internal__: { + hasHeaders: true, + hasCA: false, + }, + }, + isValid: true, + }); + }); + }); + + it('succeeds with hasAuth=false', async () => { + const testFormData = { + config: { + ...defaultTestFormData.config, + hasAuth: false, + }, + }; + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + headers: [{ key: 'content-type', value: 'text' }], + hasAuth: false, + authType: null, + }, + __internal__: { + hasHeaders: true, + hasCA: false, + }, + }, + isValid: true, + }); + }); + }); + + it('succeeds without headers', async () => { + const testConfig = { + config: { + hasAuth: true, + authType: AuthType.Basic, + }, + secrets: { + user: 'user', + password: 'pass', + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + hasAuth: true, + authType: AuthType.Basic, + }, + secrets: { + user: 'user', + password: 'pass', + }, + __internal__: { + hasHeaders: false, + hasCA: false, + }, + }, + isValid: true, + }); + }); + }); + + it('succeeds with CA and verificationMode', async () => { + const testConfig = { + ...defaultTestFormData, + config: { + ...defaultTestFormData.config, + ca: Buffer.from('some binary string').toString('base64'), + verificationMode: 'full', + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + hasAuth: true, + authType: AuthType.Basic, + ca: Buffer.from('some binary string').toString('base64'), + verificationMode: 'full', + headers: [{ key: 'content-type', value: 'text' }], + }, + secrets: { + user: 'user', + password: 'pass', + }, + __internal__: { + hasHeaders: true, + hasCA: true, + }, + }, + isValid: true, + }); + }); + }); + + it('fails with hasCa=true and a missing CA', async () => { + const testConfig = { + ...defaultTestFormData, + config: { + ...defaultTestFormData.config, + verificationMode: 'full', + }, + __internal__: { + hasHeaders: true, + hasCA: true, + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: {}, + isValid: false, + }); + }); + }); + + it('succeeds with authType=SSL and a CRT and KEY', async () => { + const testConfig = { + config: { + ...defaultTestFormData.config, + authType: AuthType.SSL, + certType: SSLCertType.CRT, + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + key: Buffer.from('some binary string').toString('base64'), + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + hasAuth: true, + authType: AuthType.SSL, + certType: SSLCertType.CRT, + headers: [{ key: 'content-type', value: 'text' }], + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + key: Buffer.from('some binary string').toString('base64'), + }, + __internal__: { + hasHeaders: true, + hasCA: false, + }, + }, + isValid: true, + }); + }); + }); + + it('succeeds with authType=SSL and a PFX', async () => { + const testConfig = { + config: { + ...defaultTestFormData.config, + authType: AuthType.SSL, + certType: SSLCertType.PFX, + }, + secrets: { + pfx: Buffer.from('some binary string').toString('base64'), + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + hasAuth: true, + authType: AuthType.SSL, + certType: SSLCertType.PFX, + headers: [{ key: 'content-type', value: 'text' }], + }, + secrets: { + pfx: Buffer.from('some binary string').toString('base64'), + }, + __internal__: { + hasHeaders: true, + hasCA: false, + }, + }, + isValid: true, + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/stack_connectors/public/common/auth/auth_config.tsx b/x-pack/plugins/stack_connectors/public/common/auth/auth_config.tsx new file mode 100644 index 0000000000000..e4477be874ecb --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/auth_config.tsx @@ -0,0 +1,292 @@ +/* + * Copyright 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, { FunctionComponent, useEffect } from 'react'; + +import { + EuiButtonEmpty, + EuiButtonIcon, + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { + UseArray, + UseField, + useFormContext, + useFormData, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { + ToggleField, + TextField, + CardRadioGroupField, + HiddenField, + FilePickerField, + SelectField, +} from '@kbn/es-ui-shared-plugin/static/forms/components'; + +import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; +import { AuthType, SSLCertType } from '../../../common/auth/constants'; +import { SSLCertFields } from './ssl_cert_fields'; +import { BasicAuthFields } from './basic_auth_fields'; +import * as i18n from './translations'; + +interface Props { + readOnly: boolean; + hideSSL?: boolean; +} + +const { emptyField } = fieldValidators; + +const VERIFICATION_MODE_DEFAULT = 'full'; + +export const AuthConfig: FunctionComponent = ({ readOnly, hideSSL }) => { + const { setFieldValue, getFieldDefaultValue } = useFormContext(); + const [{ config, __internal__ }] = useFormData({ + watch: [ + 'config.hasAuth', + 'config.authType', + 'config.certType', + 'config.verificationMode', + '__internal__.hasHeaders', + '__internal__.hasCA', + ], + }); + + const authType = config == null ? AuthType.Basic : config.authType; + const certType = config == null ? SSLCertType.CRT : config.certType; + const hasHeaders = __internal__ != null ? __internal__.hasHeaders : false; + const hasCA = __internal__ != null ? __internal__.hasCA : false; + const hasInitialCA = !!getFieldDefaultValue('config.ca'); + const hasHeadersDefaultValue = !!getFieldDefaultValue('config.headers'); + const authTypeDefaultValue = + getFieldDefaultValue('config.hasAuth') === false + ? null + : getFieldDefaultValue('config.authType') ?? AuthType.Basic; + const certTypeDefaultValue: SSLCertType = + getFieldDefaultValue('config.certType') ?? SSLCertType.CRT; + const hasCADefaultValue = + !!getFieldDefaultValue('config.ca') || + getFieldDefaultValue('config.verificationMode') === 'none'; + + useEffect(() => setFieldValue('config.hasAuth', Boolean(authType)), [authType, setFieldValue]); + + const hideSSLFields = hideSSL && authType !== AuthType.SSL; + + const authOptions = [ + { + value: null, + label: i18n.AUTHENTICATION_NONE, + 'data-test-subj': 'authNone', + }, + { + value: AuthType.Basic, + label: i18n.AUTHENTICATION_BASIC, + children: authType === AuthType.Basic && , + 'data-test-subj': 'authBasic', + }, + ]; + + if (!hideSSLFields) { + authOptions.push({ + value: AuthType.SSL, + label: i18n.AUTHENTICATION_SSL, + children: authType === AuthType.SSL && ( + + ), + 'data-test-subj': 'authSSL', + }); + } + + return ( + <> + + + +

{i18n.AUTHENTICATION_TITLE}

+ + +
+ + + + + + {hasHeaders && ( + + {({ items, addItem, removeItem }) => { + return ( + <> + +
{i18n.HEADERS_TITLE}
+
+ + {items.map((item) => ( + + + + + + + + + removeItem(item.id)} + iconType="minusInCircle" + aria-label={i18n.DELETE_BUTTON} + style={{ marginTop: '28px' }} + /> + + + ))} + + + {i18n.ADD_BUTTON} + + + + ); + }} +
+ )} + + {!hideSSLFields && ( + <> + + {hasCA && ( + <> + + + + {}, + }, + ], + }} + component={FilePickerField} + componentProps={{ + euiFieldProps: { + display: 'default', + 'data-test-subj': 'webhookCAInput', + accept: '.ca,.pem', + }, + }} + /> + + + + + + {hasInitialCA && ( + <> + + + + )} + + )} + + )} + + ); +}; diff --git a/x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.test.tsx b/x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.test.tsx new file mode 100644 index 0000000000000..6d740be7b270e --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.test.tsx @@ -0,0 +1,112 @@ +/* + * Copyright 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 { BasicAuthFields } from './basic_auth_fields'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { AuthFormTestProvider } from '../../connector_types/lib/test_utils'; + +describe('BasicAuthFields', () => { + const onSubmit = jest.fn(); + + it('renders all fields', async () => { + const testFormData = { + secrets: { + user: 'user', + password: 'pass', + }, + }; + + render( + + + + ); + + expect(await screen.findByTestId('basicAuthFields')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookUserInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookPasswordInput')).toBeInTheDocument(); + }); + + describe('Validation', () => { + const defaultTestFormData = { + secrets: { + user: 'user', + password: 'pass', + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('validation succeeds with correct fields', async () => { + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + secrets: { + user: 'user', + password: 'pass', + }, + }, + isValid: true, + }); + }); + }); + + it('validates correctly missing user', async () => { + const testConfig = { + secrets: { + user: '', + password: 'password', + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false }); + }); + }); + + it('validates correctly missing password', async () => { + const testConfig = { + secrets: { + user: 'user', + password: '', + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false }); + }); + }); + }); +}); diff --git a/x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.tsx b/x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.tsx new file mode 100644 index 0000000000000..5b26f0e888e2b --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/basic_auth_fields.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Field, PasswordField } from '@kbn/es-ui-shared-plugin/static/forms/components'; +import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; + +import * as i18n from './translations'; + +const { emptyField } = fieldValidators; + +interface BasicAuthProps { + readOnly: boolean; +} + +export const BasicAuthFields: React.FC = ({ readOnly }) => ( + + + + + + + + +); diff --git a/x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.test.tsx b/x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.test.tsx new file mode 100644 index 0000000000000..9a39926b21324 --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.test.tsx @@ -0,0 +1,223 @@ +/* + * Copyright 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 { SSLCertFields } from './ssl_cert_fields'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { SSLCertType } from '../../../common/auth/constants'; +import { AuthFormTestProvider } from '../../connector_types/lib/test_utils'; + +const certTypeDefaultValue: SSLCertType = SSLCertType.CRT; + +describe('SSLCertFields', () => { + const onSubmit = jest.fn(); + + it('renders all fields for certType=CRT', async () => { + render( + + + + ); + + expect(await screen.findByTestId('sslCertFields')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookSSLPassphraseInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCertTypeTabs')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookSSLCRTInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookSSLKEYInput')).toBeInTheDocument(); + }); + + it('renders all fields for certType=PFX', async () => { + render( + + + + ); + + expect(await screen.findByTestId('sslCertFields')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookSSLPassphraseInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCertTypeTabs')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookSSLPFXInput')).toBeInTheDocument(); + }); + + describe('Validation', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('validates correctly with a PFX', async () => { + const testConfig = { + config: { + certType: SSLCertType.PFX, + }, + secrets: { + pfx: Buffer.from('some binary string').toString('base64'), + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + certType: SSLCertType.PFX, + }, + secrets: { + pfx: Buffer.from('some binary string').toString('base64'), + }, + }, + isValid: true, + }); + }); + }); + + it('validates correctly a missing PFX', async () => { + const testConfig = { + config: { + certType: SSLCertType.PFX, + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: {}, + isValid: false, + }); + }); + }); + + it('validates correctly with a CRT and KEY', async () => { + const testConfig = { + config: { + certType: SSLCertType.CRT, + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + key: Buffer.from('some binary string').toString('base64'), + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: { + config: { + certType: SSLCertType.CRT, + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + key: Buffer.from('some binary string').toString('base64'), + }, + }, + isValid: true, + }); + }); + }); + + it('validates correctly with a CRT but a missing KEY', async () => { + const testConfig = { + config: { + certType: SSLCertType.CRT, + }, + secrets: { + crt: Buffer.from('some binary string').toString('base64'), + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: {}, + isValid: false, + }); + }); + }); + + it('validates correctly with a KEY but a missing CRT', async () => { + const testConfig = { + config: { + certType: SSLCertType.CRT, + }, + secrets: { + key: Buffer.from('some binary string').toString('base64'), + }, + }; + + render( + + + + ); + + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledWith({ + data: {}, + isValid: false, + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.tsx b/x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.tsx new file mode 100644 index 0000000000000..cf9dc672dde33 --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/ssl_cert_fields.tsx @@ -0,0 +1,138 @@ +/* + * Copyright 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 { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui'; +import { UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { PasswordField } from '@kbn/es-ui-shared-plugin/static/forms/components'; +import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; +import { FilePickerField } from '@kbn/es-ui-shared-plugin/static/forms/components'; + +import { SSLCertType } from '../../../common/auth/constants'; +import * as i18n from './translations'; + +const { emptyField } = fieldValidators; + +interface BasicAuthProps { + readOnly: boolean; + certTypeDefaultValue: SSLCertType; + certType: SSLCertType; +} + +export const SSLCertFields: React.FC = ({ + readOnly, + certTypeDefaultValue, + certType, +}) => ( + + + + + ( + + field.setValue(SSLCertType.CRT)} + isSelected={field.value === SSLCertType.CRT} + > + {i18n.CERT_TYPE_CRT_KEY} + + field.setValue(SSLCertType.PFX)} + isSelected={field.value === SSLCertType.PFX} + > + {i18n.CERT_TYPE_PFX} + + + )} + /> + + {certType === SSLCertType.CRT && ( + + + + + + + + + )} + {certType === SSLCertType.PFX && ( + + )} + + +); diff --git a/x-pack/plugins/stack_connectors/public/common/auth/translations.ts b/x-pack/plugins/stack_connectors/public/common/auth/translations.ts new file mode 100644 index 0000000000000..88d97bef6364d --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/common/auth/translations.ts @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const AUTHENTICATION_TITLE = i18n.translate( + 'xpack.stackConnectors.components.auth.authenticationTitle', + { + defaultMessage: 'Authentication', + } +); + +export const AUTHENTICATION_NONE = i18n.translate( + 'xpack.stackConnectors.components.auth.authenticationMethodNoneLabel', + { + defaultMessage: 'None', + } +); + +export const AUTHENTICATION_BASIC = i18n.translate( + 'xpack.stackConnectors.components.auth.authenticationMethodBasicLabel', + { + defaultMessage: 'Basic authentication', + } +); + +export const AUTHENTICATION_SSL = i18n.translate( + 'xpack.stackConnectors.components.auth.authenticationMethodSSLLabel', + { + defaultMessage: 'SSL authentication', + } +); + +export const USERNAME = i18n.translate('xpack.stackConnectors.components.auth.userTextFieldLabel', { + defaultMessage: 'Username', +}); + +export const PASSWORD = i18n.translate( + 'xpack.stackConnectors.components.auth.passwordTextFieldLabel', + { + defaultMessage: 'Password', + } +); + +export const USERNAME_REQUIRED = i18n.translate( + 'xpack.stackConnectors.components.auth.error.requiredAuthUserNameText', + { + defaultMessage: 'Username is required.', + } +); + +export const PASSWORD_REQUIRED = i18n.translate( + 'xpack.stackConnectors.components.auth.error.requiredAuthPasswordText', + { + defaultMessage: 'Password is required.', + } +); + +export const CERT_TYPE_CRT_KEY = i18n.translate( + 'xpack.stackConnectors.components.auth.certTypeCrtKeyLabel', + { + defaultMessage: 'CRT and KEY file', + } +); +export const CERT_TYPE_PFX = i18n.translate( + 'xpack.stackConnectors.components.auth.certTypePfxLabel', + { + defaultMessage: 'PFX file', + } +); + +export const CRT_REQUIRED = i18n.translate( + 'xpack.stackConnectors.components.auth.error.requiredCRTText', + { + defaultMessage: 'CRT file is required.', + } +); + +export const KEY_REQUIRED = i18n.translate( + 'xpack.stackConnectors.components.auth.error.requiredKEYText', + { + defaultMessage: 'KEY file is required.', + } +); + +export const PFX_REQUIRED = i18n.translate( + 'xpack.stackConnectors.components.auth.error.requiredPFXText', + { + defaultMessage: 'PFX file is required.', + } +); + +export const HEADERS_SWITCH = i18n.translate( + 'xpack.stackConnectors.components.auth.viewHeadersSwitch', + { + defaultMessage: 'Add HTTP header', + } +); + +export const HEADERS_TITLE = i18n.translate( + 'xpack.stackConnectors.components.auth.httpHeadersTitle', + { + defaultMessage: 'Headers in use', + } +); + +export const KEY_LABEL = i18n.translate('xpack.stackConnectors.components.auth.keyTextFieldLabel', { + defaultMessage: 'Key', +}); + +export const VALUE_LABEL = i18n.translate( + 'xpack.stackConnectors.components.auth.valueTextFieldLabel', + { + defaultMessage: 'Value', + } +); + +export const ADD_BUTTON = i18n.translate('xpack.stackConnectors.components.auth.addHeaderButton', { + defaultMessage: 'Add', +}); + +export const DELETE_BUTTON = i18n.translate( + 'xpack.stackConnectors.components.auth.deleteHeaderButton', + { + defaultMessage: 'Delete', + description: 'Delete HTTP header', + } +); + +export const CA_REQUIRED = i18n.translate( + 'xpack.stackConnectors.components.auth.error.requiredCAText', + { + defaultMessage: 'CA file is required.', + } +); + +export const ADD_CA_LABEL = i18n.translate( + 'xpack.stackConnectors.components.auth.viewCertificateAuthoritySwitch', + { + defaultMessage: 'Add certificate authority', + } +); + +export const VERIFICATION_MODE_LABEL = i18n.translate( + 'xpack.stackConnectors.components.auth.verificationModeFieldLabel', + { defaultMessage: 'Verification mode' } +); + +export const EDIT_CA_CALLOUT = i18n.translate( + 'xpack.stackConnectors.components.auth.editCACallout', + { + defaultMessage: + 'This connector has an existing certificate authority file. Upload a new one to replace it.', + } +); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/steps/auth.tsx b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/steps/auth.tsx index f27ad80ae942c..3d7b5bf27e173 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/steps/auth.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/steps/auth.tsx @@ -6,25 +6,10 @@ */ import React, { FunctionComponent } from 'react'; -import { - EuiButtonEmpty, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiTitle, -} from '@elastic/eui'; -import { - FIELD_TYPES, - UseArray, - UseField, - useFormContext, - useFormData, -} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -import { Field, TextField, PasswordField } from '@kbn/es-ui-shared-plugin/static/forms/components'; -import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; -import * as i18n from '../translations'; -const { emptyField } = fieldValidators; + +import { EuiSpacer } from '@elastic/eui'; + +import { AuthConfig } from '../../../common/auth/auth_config'; interface Props { display: boolean; @@ -32,158 +17,10 @@ interface Props { } export const AuthStep: FunctionComponent = ({ display, readOnly }) => { - const { getFieldDefaultValue } = useFormContext(); - const [{ config, __internal__ }] = useFormData({ - watch: ['config.hasAuth', '__internal__.hasHeaders'], - }); - - const hasHeadersDefaultValue = !!getFieldDefaultValue('config.headers'); - - const hasAuth = config == null ? true : config.hasAuth; - const hasHeaders = __internal__ != null ? __internal__.hasHeaders : false; - return ( - - - -

{i18n.AUTH_TITLE}

-
- - -
-
- {hasAuth ? ( - - - - - - - - - ) : null} - - - - {hasHeaders ? ( - - {({ items, addItem, removeItem }) => { - return ( - <> - -
{i18n.HEADERS_TITLE}
-
- - {items.map((item) => ( - - - - - - - - - removeItem(item.id)} - iconType="minusInCircle" - aria-label={i18n.DELETE_BUTTON} - style={{ marginTop: '28px' }} - /> - - - ))} - - - {i18n.ADD_BUTTON} - - - - ); - }} -
- ) : null} + +
); }; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/translations.ts b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/translations.ts index 02b45786c362f..5986126d17adc 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/translations.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/translations.ts @@ -112,20 +112,6 @@ export const MISSING_VARIABLES = (variables: string[]) => values: { variableCount: variables.length, variables: variables.join(', ') }, }); -export const USERNAME_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.error.requiredAuthUserNameText', - { - defaultMessage: 'Username is required.', - } -); - -export const PASSWORD_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.error.requiredAuthPasswordText', - { - defaultMessage: 'Password is required.', - } -); - export const SUMMARY_REQUIRED = i18n.translate( 'xpack.stackConnectors.components.casesWebhook.error.requiredWebhookSummaryText', { @@ -133,35 +119,6 @@ export const SUMMARY_REQUIRED = i18n.translate( } ); -export const KEY_LABEL = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.keyTextFieldLabel', - { - defaultMessage: 'Key', - } -); - -export const VALUE_LABEL = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.valueTextFieldLabel', - { - defaultMessage: 'Value', - } -); - -export const ADD_BUTTON = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.addHeaderButton', - { - defaultMessage: 'Add', - } -); - -export const DELETE_BUTTON = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.deleteHeaderButton', - { - defaultMessage: 'Delete', - description: 'Delete HTTP header', - } -); - export const CREATE_INCIDENT_METHOD = i18n.translate( 'xpack.stackConnectors.components.casesWebhook.createIncidentMethodTextFieldLabel', { @@ -338,41 +295,6 @@ export const HAS_AUTH = i18n.translate( } ); -export const USERNAME = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.userTextFieldLabel', - { - defaultMessage: 'Username', - } -); - -export const PASSWORD = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.passwordTextFieldLabel', - { - defaultMessage: 'Password', - } -); - -export const HEADERS_SWITCH = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.viewHeadersSwitch', - { - defaultMessage: 'Add HTTP header', - } -); - -export const HEADERS_TITLE = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.httpHeadersTitle', - { - defaultMessage: 'Headers in use', - } -); - -export const AUTH_TITLE = i18n.translate( - 'xpack.stackConnectors.components.casesWebhook.authenticationLabel', - { - defaultMessage: 'Authentication', - } -); - export const STEP_1 = i18n.translate('xpack.stackConnectors.components.casesWebhook.step1', { defaultMessage: 'Set up connector', }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_connectors.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_connectors.test.tsx index b06f7accae307..66d15550b7b75 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_connectors.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_connectors.test.tsx @@ -7,8 +7,9 @@ import React from 'react'; import CasesWebhookActionConnectorFields from './webhook_connectors'; -import { ConnectorFormTestProvider, waitForComponentToUpdate } from '../lib/test_utils'; -import { act, render } from '@testing-library/react'; +import { ConnectorFormTestProvider } from '../lib/test_utils'; +import { render, screen, waitFor } from '@testing-library/react'; +import { AuthType } from '../../../common/auth/constants'; import userEvent from '@testing-library/user-event'; import * as i18n from './translations'; @@ -27,6 +28,7 @@ jest.mock('@kbn/triggers-actions-ui-plugin/public', () => { const invalidJsonTitle = `{"fields":{"summary":"wrong","description":{{{case.description}}},"project":{"key":"ROC"},"issuetype":{"id":"10024"}}}`; const invalidJsonBoth = `{"fields":{"summary":"wrong","description":"wrong","project":{"key":"ROC"},"issuetype":{"id":"10024"}}}`; const config = { + authType: AuthType.Basic, createCommentJson: '{"body":{{{case.comment}}}}', createCommentMethod: 'post', createCommentUrl: 'https://coolsite.net/rest/api/2/issue/{{{external.system.id}}}/comment', @@ -59,8 +61,8 @@ const actionConnector = { }; describe('CasesWebhookActionConnectorFields renders', () => { - test('All inputs are properly rendered', async () => { - const { getByTestId } = render( + it('All inputs are properly rendered', async () => { + render( { /> ); - await waitForComponentToUpdate(); - expect(getByTestId('webhookUserInput')).toBeInTheDocument(); - expect(getByTestId('webhookPasswordInput')).toBeInTheDocument(); - expect(getByTestId('webhookHeadersKeyInput')).toBeInTheDocument(); - expect(getByTestId('webhookHeadersValueInput')).toBeInTheDocument(); - expect(getByTestId('webhookCreateMethodSelect')).toBeInTheDocument(); - expect(getByTestId('webhookCreateUrlText')).toBeInTheDocument(); - expect(getByTestId('webhookCreateIncidentJson')).toBeInTheDocument(); - expect(getByTestId('createIncidentResponseKeyText')).toBeInTheDocument(); - expect(getByTestId('getIncidentUrlInput')).toBeInTheDocument(); - expect(getByTestId('getIncidentResponseExternalTitleKeyText')).toBeInTheDocument(); - expect(getByTestId('viewIncidentUrlInput')).toBeInTheDocument(); - expect(getByTestId('webhookUpdateMethodSelect')).toBeInTheDocument(); - expect(getByTestId('updateIncidentUrlInput')).toBeInTheDocument(); - expect(getByTestId('webhookUpdateIncidentJson')).toBeInTheDocument(); - expect(getByTestId('webhookCreateCommentMethodSelect')).toBeInTheDocument(); - expect(getByTestId('createCommentUrlInput')).toBeInTheDocument(); - expect(getByTestId('webhookCreateCommentJson')).toBeInTheDocument(); + + expect(await screen.findByTestId('authNone')).toBeInTheDocument(); + expect(await screen.findByTestId('authBasic')).toBeInTheDocument(); + // expect(await screen.findByTestId('authSSL')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookUserInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookPasswordInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeadersKeyInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookHeadersValueInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCreateMethodSelect')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCreateUrlText')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCreateIncidentJson')).toBeInTheDocument(); + expect(await screen.findByTestId('createIncidentResponseKeyText')).toBeInTheDocument(); + expect(await screen.findByTestId('getIncidentUrlInput')).toBeInTheDocument(); + expect( + await screen.findByTestId('getIncidentResponseExternalTitleKeyText') + ).toBeInTheDocument(); + expect(await screen.findByTestId('viewIncidentUrlInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookUpdateMethodSelect')).toBeInTheDocument(); + expect(await screen.findByTestId('updateIncidentUrlInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookUpdateIncidentJson')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCreateCommentMethodSelect')).toBeInTheDocument(); + expect(await screen.findByTestId('createCommentUrlInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookCreateCommentJson')).toBeInTheDocument(); }); - test('Toggles work properly', async () => { - const { getByTestId, queryByTestId } = render( + + it('connector auth toggles work as expected', async () => { + render( { /> ); - await waitForComponentToUpdate(); - expect(getByTestId('hasAuthToggle')).toHaveAttribute('aria-checked', 'true'); - await act(async () => { - userEvent.click(getByTestId('hasAuthToggle')); - }); - expect(getByTestId('hasAuthToggle')).toHaveAttribute('aria-checked', 'false'); - expect(queryByTestId('webhookUserInput')).not.toBeInTheDocument(); - expect(queryByTestId('webhookPasswordInput')).not.toBeInTheDocument(); - expect(getByTestId('webhookViewHeadersSwitch')).toHaveAttribute('aria-checked', 'true'); - await act(async () => { - userEvent.click(getByTestId('webhookViewHeadersSwitch')); - }); - expect(getByTestId('webhookViewHeadersSwitch')).toHaveAttribute('aria-checked', 'false'); - expect(queryByTestId('webhookHeadersKeyInput')).not.toBeInTheDocument(); - expect(queryByTestId('webhookHeadersValueInput')).not.toBeInTheDocument(); + const authNoneToggle = await screen.findByTestId('authNone'); + + expect(authNoneToggle).toBeInTheDocument(); + expect(await screen.findByTestId('authBasic')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookUserInput')).toBeInTheDocument(); + expect(await screen.findByTestId('webhookPasswordInput')).toBeInTheDocument(); + + userEvent.click(authNoneToggle); + + expect(screen.queryByTestId('webhookUserInput')).not.toBeInTheDocument(); + expect(screen.queryByTestId('webhookPasswordInput')).not.toBeInTheDocument(); + + expect(await screen.findByTestId('webhookViewHeadersSwitch')).toHaveAttribute( + 'aria-checked', + 'true' + ); + userEvent.click(await screen.findByTestId('webhookViewHeadersSwitch')); + expect(await screen.findByTestId('webhookViewHeadersSwitch')).toHaveAttribute( + 'aria-checked', + 'false' + ); + expect(screen.queryByTestId('webhookHeadersKeyInput')).not.toBeInTheDocument(); + expect(screen.queryByTestId('webhookHeadersValueInput')).not.toBeInTheDocument(); }); + describe('Step Validation', () => { - test('Steps work correctly when all fields valid', async () => { - const { queryByTestId, getByTestId } = render( + it('Steps work correctly when all fields valid', async () => { + render( { /> ); - await waitForComponentToUpdate(); - expect(getByTestId('horizontalStep1-current')).toBeInTheDocument(); - expect(getByTestId('horizontalStep2-incomplete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep3-incomplete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); - expect(getByTestId('authStep')).toHaveAttribute('style', 'display: block;'); - expect(getByTestId('createStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('getStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('updateStep')).toHaveAttribute('style', 'display: none;'); - expect(queryByTestId('casesWebhookBack')).not.toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - expect(getByTestId('horizontalStep1-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep2-current')).toBeInTheDocument(); - expect(getByTestId('horizontalStep3-incomplete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); - expect(getByTestId('authStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('createStep')).toHaveAttribute('style', 'display: block;'); - expect(getByTestId('getStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('updateStep')).toHaveAttribute('style', 'display: none;'); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - expect(getByTestId('horizontalStep1-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep2-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep3-current')).toBeInTheDocument(); - expect(getByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); - expect(getByTestId('authStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('createStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('getStep')).toHaveAttribute('style', 'display: block;'); - expect(getByTestId('updateStep')).toHaveAttribute('style', 'display: none;'); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - expect(getByTestId('horizontalStep1-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep2-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep3-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep4-current')).toBeInTheDocument(); - expect(getByTestId('authStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('createStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('getStep')).toHaveAttribute('style', 'display: none;'); - expect(getByTestId('updateStep')).toHaveAttribute('style', 'display: block;'); - expect(queryByTestId('casesWebhookNext')).not.toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep1-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('authStep')).toHaveAttribute('style', 'display: block;'); + expect(await screen.findByTestId('createStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('getStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('updateStep')).toHaveAttribute('style', 'display: none;'); + expect(screen.queryByTestId('casesWebhookBack')).not.toBeInTheDocument(); + + userEvent.click(await screen.findByTestId('casesWebhookNext')); + + expect(await screen.findByTestId('horizontalStep1-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('authStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('createStep')).toHaveAttribute('style', 'display: block;'); + expect(await screen.findByTestId('getStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('updateStep')).toHaveAttribute('style', 'display: none;'); + + userEvent.click(await screen.findByTestId('casesWebhookNext')); + + expect(await screen.findByTestId('horizontalStep1-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('authStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('createStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('getStep')).toHaveAttribute('style', 'display: block;'); + expect(await screen.findByTestId('updateStep')).toHaveAttribute('style', 'display: none;'); + + userEvent.click(await screen.findByTestId('casesWebhookNext')); + + expect(await screen.findByTestId('horizontalStep1-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep4-current')).toBeInTheDocument(); + expect(await screen.findByTestId('authStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('createStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('getStep')).toHaveAttribute('style', 'display: none;'); + expect(await screen.findByTestId('updateStep')).toHaveAttribute('style', 'display: block;'); + expect(screen.queryByTestId('casesWebhookNext')).not.toBeInTheDocument(); }); - test('Step 1 is properly validated', async () => { + + it('Step 1 is properly validated', async () => { const incompleteActionConnector = { ...actionConnector, secrets: { @@ -179,7 +196,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { password: '', }, }; - const { getByTestId } = render( + render( { /> ); - await waitForComponentToUpdate(); - expect(getByTestId('horizontalStep1-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep1-current')).toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - await waitForComponentToUpdate(); + userEvent.click(await screen.findByTestId('casesWebhookNext')); - expect(getByTestId('horizontalStep1-danger')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep1-danger')).toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('hasAuthToggle')); - userEvent.click(getByTestId('webhookViewHeadersSwitch')); - }); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); + userEvent.click(await screen.findByTestId('authNone')); + userEvent.click(await screen.findByTestId('webhookViewHeadersSwitch')); + userEvent.click(await screen.findByTestId('casesWebhookNext')); - expect(getByTestId('horizontalStep1-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep2-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep1-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-current')).toBeInTheDocument(); }); - test('Step 2 is properly validated', async () => { + + it('Step 2 is properly validated', async () => { const incompleteActionConnector = { ...actionConnector, config: { @@ -218,7 +228,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { createIncidentUrl: undefined, }, }; - const { getByText, getByTestId } = render( + render( { /> ); - await waitForComponentToUpdate(); - expect(getByTestId('horizontalStep2-incomplete')).toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - getByText(i18n.CREATE_URL_REQUIRED); - expect(getByTestId('horizontalStep2-danger')).toBeInTheDocument(); - await act(async () => { - await userEvent.type( - getByTestId('webhookCreateUrlText'), - `{selectall}{backspace}${config.createIncidentUrl}`, - { - delay: 10, - } - ); - }); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - expect(getByTestId('horizontalStep2-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep3-current')).toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('horizontalStep2-complete')); - }); - expect(getByTestId('horizontalStep2-current')).toBeInTheDocument(); - expect(getByTestId('horizontalStep3-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-incomplete')).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('casesWebhookNext')); + userEvent.click(await screen.findByTestId('casesWebhookNext')); + expect(await screen.findByText(i18n.CREATE_URL_REQUIRED)).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-danger')).toBeInTheDocument(); + await userEvent.type( + await screen.findByTestId('webhookCreateUrlText'), + `{selectall}{backspace}${config.createIncidentUrl}`, + { + delay: 10, + } + ); + + userEvent.click(await screen.findByTestId('casesWebhookNext')); + + expect(await screen.findByTestId('horizontalStep2-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-current')).toBeInTheDocument(); + + userEvent.click(await screen.findByTestId('horizontalStep2-complete')); + + expect(await screen.findByTestId('horizontalStep2-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-incomplete')).toBeInTheDocument(); }); - test('Step 3 is properly validated', async () => { + + it('Step 3 is properly validated', async () => { const incompleteActionConnector = { ...actionConnector, config: { @@ -265,7 +269,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { getIncidentResponseExternalTitleKey: undefined, }, }; - const { getByText, getByTestId } = render( + render( { /> ); - await waitForComponentToUpdate(); - expect(getByTestId('horizontalStep2-incomplete')).toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - getByText(i18n.GET_RESPONSE_EXTERNAL_TITLE_KEY_REQUIRED); - expect(getByTestId('horizontalStep3-danger')).toBeInTheDocument(); - await act(async () => { - await userEvent.type( - getByTestId('getIncidentResponseExternalTitleKeyText'), - `{selectall}{backspace}${config.getIncidentResponseExternalTitleKey}`, - { - delay: 10, - } - ); - }); - await act(async () => { - userEvent.click(getByTestId('casesWebhookNext')); - }); - expect(getByTestId('horizontalStep3-complete')).toBeInTheDocument(); - expect(getByTestId('horizontalStep4-current')).toBeInTheDocument(); - await act(async () => { - userEvent.click(getByTestId('horizontalStep3-complete')); - }); - expect(getByTestId('horizontalStep3-current')).toBeInTheDocument(); - expect(getByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep2-incomplete')).toBeInTheDocument(); + + userEvent.click(await screen.findByTestId('casesWebhookNext')); + userEvent.click(await screen.findByTestId('casesWebhookNext')); + userEvent.click(await screen.findByTestId('casesWebhookNext')); + + expect( + await screen.findByText(i18n.GET_RESPONSE_EXTERNAL_TITLE_KEY_REQUIRED) + ).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep3-danger')).toBeInTheDocument(); + + await userEvent.type( + await screen.findByTestId('getIncidentResponseExternalTitleKeyText'), + `{selectall}{backspace}${config.getIncidentResponseExternalTitleKey}`, + { + delay: 10, + } + ); + + userEvent.click(await screen.findByTestId('casesWebhookNext')); + + expect(await screen.findByTestId('horizontalStep3-complete')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep4-current')).toBeInTheDocument(); + + userEvent.click(await screen.findByTestId('horizontalStep3-complete')); + + expect(await screen.findByTestId('horizontalStep3-current')).toBeInTheDocument(); + expect(await screen.findByTestId('horizontalStep4-incomplete')).toBeInTheDocument(); }); // step 4 is not validated like the others since it is the last step @@ -346,7 +346,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { ]; it('connector validation succeeds when connector config is valid', async () => { - const { getByTestId } = render( + render( { ); - await act(async () => { - userEvent.click(getByTestId('form-test-provide-submit')); - }); + userEvent.click(await screen.findByTestId('form-test-provide-submit')); const { isPreconfigured, ...rest } = actionConnector; - - expect(onSubmit).toBeCalledWith({ - data: { - ...rest, - __internal__: { - hasHeaders: true, + await waitFor(() => + expect(onSubmit).toBeCalledWith({ + data: { + ...rest, + __internal__: { + // hasCA: false, + hasHeaders: true, + }, }, - }, - isValid: true, - }); + isValid: true, + }) + ); }); it('connector validation succeeds when auth=false', async () => { @@ -381,7 +381,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { }, }; - const { getByTestId } = render( + render( { ); - await act(async () => { - userEvent.click(getByTestId('form-test-provide-submit')); - }); + userEvent.click(await screen.findByTestId('form-test-provide-submit')); const { isPreconfigured, secrets, ...rest } = actionConnector; - expect(onSubmit).toBeCalledWith({ - data: { - ...rest, - config: { - ...actionConnector.config, - hasAuth: false, - }, - __internal__: { - hasHeaders: true, + await waitFor(() => + expect(onSubmit).toBeCalledWith({ + data: { + ...rest, + config: { + ...actionConnector.config, + hasAuth: false, + authType: null, + }, + __internal__: { + // hasCA: false, + hasHeaders: true, + }, }, - }, - isValid: true, - }); + isValid: true, + }) + ); }); it('connector validation succeeds without headers', async () => { @@ -420,7 +422,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { }, }; - const { getByTestId } = render( + render( { ); - await act(async () => { - userEvent.click(getByTestId('form-test-provide-submit')); - }); + userEvent.click(await screen.findByTestId('form-test-provide-submit')); const { isPreconfigured, ...rest } = actionConnector; const { headers, ...rest2 } = actionConnector.config; - expect(onSubmit).toBeCalledWith({ - data: { - ...rest, - config: rest2, - __internal__: { - hasHeaders: false, + await waitFor(() => + expect(onSubmit).toBeCalledWith({ + data: { + ...rest, + config: rest2, + __internal__: { + // hasCA: false, + hasHeaders: false, + }, }, - }, - isValid: true, - }); + isValid: true, + }) + ); }); it('validates correctly if the method is empty', async () => { @@ -457,7 +460,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { }, }; - const res = render( + render( { ); - await act(async () => { - userEvent.click(res.getByTestId('form-test-provide-submit')); - }); - - expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false }); + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + await waitFor(() => expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false })); }); it.each(tests)('validates correctly %p', async (field, value) => { @@ -483,7 +483,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { }, }; - const res = render( + render( { ); - await act(async () => { - await userEvent.type(res.getByTestId(field), `{selectall}{backspace}${value}`, { - delay: 10, - }); + await userEvent.type(await screen.findByTestId(field), `{selectall}{backspace}${value}`, { + delay: 10, }); - await act(async () => { - userEvent.click(res.getByTestId('form-test-provide-submit')); - }); + userEvent.click(await screen.findByTestId('form-test-provide-submit')); - expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false }); + await waitFor(() => expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false })); }); it.each(mustacheTests)( @@ -518,7 +514,7 @@ describe('CasesWebhookActionConnectorFields renders', () => { }, }; - const res = render( + render( { ); - await act(async () => { - userEvent.click(res.getByTestId('form-test-provide-submit')); - }); - - expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false }); - expect(res.getByText(i18n.MISSING_VARIABLES(missingVariables))).toBeInTheDocument(); + userEvent.click(await screen.findByTestId('form-test-provide-submit')); + await waitFor(() => expect(onSubmit).toHaveBeenCalledWith({ data: {}, isValid: false })); + expect( + await screen.findByText(i18n.MISSING_VARIABLES(missingVariables)) + ).toBeInTheDocument(); } ); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/lib/test_utils.tsx b/x-pack/plugins/stack_connectors/public/connector_types/lib/test_utils.tsx index 6503cc7763469..29e0a8dd55b4b 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/lib/test_utils.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/lib/test_utils.tsx @@ -52,6 +52,21 @@ const ConnectorFormTestProviderComponent: React.FC = ({ + children, + defaultValue, + onSubmit, +}) => { + return ( + + {children} + + ); +}; + +AuthFormTestProviderComponent.displayName = 'AuthFormTestProvider'; +export const AuthFormTestProvider = React.memo(AuthFormTestProviderComponent); + const FormTestProviderComponent: React.FC = ({ children, defaultValue, diff --git a/x-pack/plugins/stack_connectors/public/connector_types/webhook/translations.ts b/x-pack/plugins/stack_connectors/public/connector_types/webhook/translations.ts index d0802fe5494b5..c6db3f0f1ef1b 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/webhook/translations.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/webhook/translations.ts @@ -14,13 +14,6 @@ export const METHOD_LABEL = i18n.translate( } ); -export const HAS_AUTH_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.hasAuthSwitchLabel', - { - defaultMessage: 'Require authentication for this webhook', - } -); - export const URL_LABEL = i18n.translate( 'xpack.stackConnectors.components.webhook.urlTextFieldLabel', { @@ -28,62 +21,6 @@ export const URL_LABEL = i18n.translate( } ); -export const USERNAME_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.userTextFieldLabel', - { - defaultMessage: 'Username', - } -); - -export const PASSWORD_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.passwordTextFieldLabel', - { - defaultMessage: 'Password', - } -); - -export const PASSPHRASE_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.passphraseTextFieldLabel', - { - defaultMessage: 'Passphrase', - } -); - -export const ADD_HEADERS_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.viewHeadersSwitch', - { - defaultMessage: 'Add HTTP header', - } -); - -export const HEADER_KEY_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.headerKeyTextFieldLabel', - { - defaultMessage: 'Key', - } -); - -export const REMOVE_ITEM_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.removeHeaderIconLabel', - { - defaultMessage: 'Key', - } -); - -export const ADD_HEADER_BTN = i18n.translate( - 'xpack.stackConnectors.components.webhook.addHeaderButtonLabel', - { - defaultMessage: 'Add header', - } -); - -export const HEADER_VALUE_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.headerValueTextFieldLabel', - { - defaultMessage: 'Value', - } -); - export const URL_INVALID = i18n.translate( 'xpack.stackConnectors.components.webhook.error.invalidUrlTextField', { @@ -98,105 +35,9 @@ export const METHOD_REQUIRED = i18n.translate( } ); -export const USERNAME_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.webhook.error.requiredAuthUserNameText', - { - defaultMessage: 'Username is required.', - } -); - export const BODY_REQUIRED = i18n.translate( 'xpack.stackConnectors.components.webhook.error.requiredWebhookBodyText', { defaultMessage: 'Body is required.', } ); - -export const PASSWORD_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.webhook.error.requiredWebhookPasswordText', - { - defaultMessage: 'Password is required.', - } -); - -export const AUTHENTICATION_NONE = i18n.translate( - 'xpack.stackConnectors.components.webhook.authenticationMethodNoneLabel', - { - defaultMessage: 'None', - } -); - -export const AUTHENTICATION_BASIC = i18n.translate( - 'xpack.stackConnectors.components.webhook.authenticationMethodBasicLabel', - { - defaultMessage: 'Basic authentication', - } -); - -export const AUTHENTICATION_SSL = i18n.translate( - 'xpack.stackConnectors.components.webhook.authenticationMethodSSLLabel', - { - defaultMessage: 'SSL authentication', - } -); - -export const CERT_TYPE_CRT_KEY = i18n.translate( - 'xpack.stackConnectors.components.webhook.certTypeCrtKeyLabel', - { - defaultMessage: 'CRT and KEY file', - } -); -export const CERT_TYPE_PFX = i18n.translate( - 'xpack.stackConnectors.components.webhook.certTypePfxLabel', - { - defaultMessage: 'PFX file', - } -); - -export const CRT_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.webhook.error.requiredWebhookCRTText', - { - defaultMessage: 'CRT file is required.', - } -); - -export const KEY_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.webhook.error.requiredWebhookKEYText', - { - defaultMessage: 'KEY file is required.', - } -); - -export const PFX_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.webhook.error.requiredWebhookPFXText', - { - defaultMessage: 'PFX file is required.', - } -); - -export const CA_REQUIRED = i18n.translate( - 'xpack.stackConnectors.components.webhook.error.requiredWebhookCAText', - { - defaultMessage: 'CA file is required.', - } -); - -export const ADD_CA_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.viewCertificateAuthoritySwitch', - { - defaultMessage: 'Add certificate authority', - } -); - -export const VERIFICATION_MODE_LABEL = i18n.translate( - 'xpack.stackConnectors.components.webhook.verificationModeFieldLabel', - { defaultMessage: 'Verification mode' } -); - -export const EDIT_CA_CALLOUT = i18n.translate( - 'xpack.stackConnectors.components.webhook.editCACallout', - { - defaultMessage: - 'This webhook has an existing certificate authority file. Upload a new one to replace it.', - } -); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.test.tsx index 6b74624caaf9a..b9e2983964457 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.test.tsx @@ -11,10 +11,10 @@ import WebhookActionConnectorFields from './webhook_connectors'; import { ConnectorFormTestProvider, waitForComponentToUpdate } from '../lib/test_utils'; import { act, render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { WebhookAuthType, SSLCertType } from '../../../common/webhook/constants'; +import { AuthType, SSLCertType } from '../../../common/auth/constants'; describe('WebhookActionConnectorFields renders', () => { - test('all connector fields is rendered', async () => { + it('renders all connector fields', async () => { const actionConnector = { actionTypeId: '.webhook', name: 'webhook', @@ -23,7 +23,7 @@ describe('WebhookActionConnectorFields renders', () => { url: 'https://test.com', headers: [{ key: 'content-type', value: 'text' }], hasAuth: true, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, }, secrets: { user: 'user', @@ -104,7 +104,7 @@ describe('WebhookActionConnectorFields renders', () => { url: 'https://test.com', headers: [{ key: 'content-type', value: 'text' }], hasAuth: true, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, }, secrets: { user: 'user', @@ -171,7 +171,7 @@ describe('WebhookActionConnectorFields renders', () => { method: 'PUT', url: 'https://test.com', hasAuth: true, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, }, }; @@ -197,7 +197,7 @@ describe('WebhookActionConnectorFields renders', () => { method: 'PUT', url: 'https://test.com', hasAuth: true, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, }, secrets: { user: 'user', @@ -303,7 +303,7 @@ describe('WebhookActionConnectorFields renders', () => { method: 'PUT', url: 'https://test.com', hasAuth: true, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, ca: Buffer.from('some binary string').toString('base64'), verificationMode: 'full', headers: [{ key: 'content-type', value: 'text' }], @@ -327,7 +327,7 @@ describe('WebhookActionConnectorFields renders', () => { ...actionConnector, config: { ...actionConnector.config, - authType: WebhookAuthType.SSL, + authType: AuthType.SSL, certType: SSLCertType.CRT, }, secrets: { @@ -358,7 +358,7 @@ describe('WebhookActionConnectorFields renders', () => { method: 'PUT', url: 'https://test.com', hasAuth: true, - authType: WebhookAuthType.SSL, + authType: AuthType.SSL, certType: SSLCertType.CRT, headers: [{ key: 'content-type', value: 'text' }], }, @@ -381,7 +381,7 @@ describe('WebhookActionConnectorFields renders', () => { ...actionConnector, config: { ...actionConnector.config, - authType: WebhookAuthType.SSL, + authType: AuthType.SSL, certType: SSLCertType.PFX, }, secrets: { @@ -411,7 +411,7 @@ describe('WebhookActionConnectorFields renders', () => { method: 'PUT', url: 'https://test.com', hasAuth: true, - authType: WebhookAuthType.SSL, + authType: AuthType.SSL, certType: SSLCertType.PFX, headers: [{ key: 'content-type', value: 'text' }], }, @@ -433,7 +433,7 @@ describe('WebhookActionConnectorFields renders', () => { ...actionConnector, config: { ...actionConnector.config, - authType: WebhookAuthType.SSL, + authType: AuthType.SSL, certType: SSLCertType.CRT, }, secrets: { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.tsx b/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.tsx index f99f0c964a578..0c567127e4811 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook_connectors.tsx @@ -5,237 +5,25 @@ * 2.0. */ -import React, { useEffect } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiButtonIcon, - EuiTitle, - EuiButtonEmpty, - EuiCallOut, - EuiTabs, - EuiTab, -} from '@elastic/eui'; -import { - UseArray, - UseField, - useFormContext, - useFormData, -} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -import { - Field, - SelectField, - TextField, - ToggleField, - PasswordField, - FilePickerField, - CardRadioGroupField, - HiddenField, -} from '@kbn/es-ui-shared-plugin/static/forms/components'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Field, SelectField } from '@kbn/es-ui-shared-plugin/static/forms/components'; import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import type { ActionConnectorFieldsProps } from '@kbn/triggers-actions-ui-plugin/public'; -import { WebhookAuthType, SSLCertType } from '../../../common/webhook/constants'; + import * as i18n from './translations'; +import { AuthConfig } from '../../common/auth/auth_config'; const HTTP_VERBS = ['post', 'put']; const { emptyField, urlField } = fieldValidators; -const VERIFICATION_MODE_DEFAULT = 'full'; const WebhookActionConnectorFields: React.FunctionComponent = ({ readOnly, }) => { - const { setFieldValue, getFieldDefaultValue } = useFormContext(); - const [{ config, __internal__ }] = useFormData({ - watch: [ - 'config.hasAuth', - 'config.authType', - 'config.certType', - 'config.verificationMode', - '__internal__.hasHeaders', - '__internal__.hasCA', - ], - }); - - const hasHeadersDefaultValue = !!getFieldDefaultValue('config.headers'); - const authTypeDefaultValue = - getFieldDefaultValue('config.hasAuth') === false - ? null - : getFieldDefaultValue('config.authType') ?? WebhookAuthType.Basic; - const certTypeDefaultValue = getFieldDefaultValue('config.certType') ?? SSLCertType.CRT; - const hasCADefaultValue = - !!getFieldDefaultValue('config.ca') || - getFieldDefaultValue('config.verificationMode') === 'none'; - - const hasHeaders = __internal__ != null ? __internal__.hasHeaders : false; - const hasCA = __internal__ != null ? __internal__.hasCA : false; - const authType = config == null ? WebhookAuthType.Basic : config.authType; - const certType = config == null ? SSLCertType.CRT : config.certType; - - const hasInitialCA = !!getFieldDefaultValue('config.ca'); - - useEffect(() => setFieldValue('config.hasAuth', Boolean(authType)), [authType, setFieldValue]); - - const basicAuthFields = ( - - - - - - - - - ); - - const sslCertAuthFields = ( - - - - - ( - - field.setValue(SSLCertType.CRT)} - isSelected={field.value === SSLCertType.CRT} - > - {i18n.CERT_TYPE_CRT_KEY} - - field.setValue(SSLCertType.PFX)} - isSelected={field.value === SSLCertType.PFX} - > - {i18n.CERT_TYPE_PFX} - - - )} - /> - - {certType === SSLCertType.CRT && ( - - - - - - - - - )} - {certType === SSLCertType.PFX && ( - - )} - - - ); - return ( <> - - - - - -

- -

-
- - -
-
- - - - {hasHeaders ? ( - <> - - - {({ items, addItem, removeItem }) => { - return ( - <> - {items.map((item) => ( - - - - - - - - - removeItem(item.id)} - iconType="minusInCircle" - aria-label={i18n.REMOVE_ITEM_LABEL} - style={{ marginTop: '28px' }} - /> - - - ))} - - - {i18n.ADD_HEADER_BTN} - - - - ); - }} - - - ) : null} - - - {hasCA && ( - <> - - - {}, - }, - ], - }} - component={FilePickerField} - componentProps={{ - euiFieldProps: { - display: 'default', - 'data-test-subj': 'webhookCAInput', - accept: '.ca,.pem', - }, - }} - /> - - - - - - {hasInitialCA && ( - <> - - - - )} - - )} + ); }; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts index 9bfb66f1a69aa..62dd881608605 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts @@ -26,12 +26,13 @@ import { ExternalIncidentServiceSecretConfigurationSchema, } from './schema'; import { api } from './api'; -import { validate } from './validators'; +import { validateCasesWebhookConfig, validateConnector } from './validators'; import * as i18n from './translations'; const supportedSubActions: string[] = ['pushToService']; export type ActionParamsType = CasesWebhookActionParamsType; export const ConnectorTypeId = '.cases-webhook'; + // connector type definition export function getConnectorType(): ConnectorType< CasesWebhookPublicConfigurationType, @@ -46,16 +47,15 @@ export function getConnectorType(): ConnectorType< validate: { config: { schema: ExternalIncidentServiceConfigurationSchema, - customValidator: validate.config, + customValidator: validateCasesWebhookConfig, }, secrets: { schema: ExternalIncidentServiceSecretConfigurationSchema, - customValidator: validate.secrets, }, params: { schema: ExecutorParamsSchema, }, - connector: validate.connector, + connector: validateConnector, }, executor, supportedFeatureIds: [CasesConnectorFeatureId], diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/schema.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/schema.ts index 9863b1457628a..00b4fdc60a3ab 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/schema.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/schema.ts @@ -6,17 +6,17 @@ */ import { schema } from '@kbn/config-schema'; -import { CasesWebhookMethods } from './types'; -import { nullableType } from '../lib/nullable'; +import { WebhookMethods } from '../../../common/auth/constants'; +import { AuthConfiguration, SecretConfigurationSchema } from '../../../common/auth/schema'; const HeadersSchema = schema.recordOf(schema.string(), schema.string()); export const ExternalIncidentServiceConfiguration = { createIncidentUrl: schema.string(), createIncidentMethod: schema.oneOf( - [schema.literal(CasesWebhookMethods.POST), schema.literal(CasesWebhookMethods.PUT)], + [schema.literal(WebhookMethods.POST), schema.literal(WebhookMethods.PUT)], { - defaultValue: CasesWebhookMethods.POST, + defaultValue: WebhookMethods.POST, } ), createIncidentJson: schema.string(), // stringified object @@ -27,12 +27,12 @@ export const ExternalIncidentServiceConfiguration = { updateIncidentUrl: schema.string(), updateIncidentMethod: schema.oneOf( [ - schema.literal(CasesWebhookMethods.POST), - schema.literal(CasesWebhookMethods.PATCH), - schema.literal(CasesWebhookMethods.PUT), + schema.literal(WebhookMethods.POST), + schema.literal(WebhookMethods.PATCH), + schema.literal(WebhookMethods.PUT), ], { - defaultValue: CasesWebhookMethods.PUT, + defaultValue: WebhookMethods.PUT, } ), updateIncidentJson: schema.string(), @@ -40,33 +40,28 @@ export const ExternalIncidentServiceConfiguration = { createCommentMethod: schema.nullable( schema.oneOf( [ - schema.literal(CasesWebhookMethods.POST), - schema.literal(CasesWebhookMethods.PUT), - schema.literal(CasesWebhookMethods.PATCH), + schema.literal(WebhookMethods.POST), + schema.literal(WebhookMethods.PUT), + schema.literal(WebhookMethods.PATCH), ], { - defaultValue: CasesWebhookMethods.PUT, + defaultValue: WebhookMethods.PUT, } ) ), createCommentJson: schema.nullable(schema.string()), - headers: nullableType(HeadersSchema), - hasAuth: schema.boolean({ defaultValue: true }), + headers: schema.nullable(HeadersSchema), + hasAuth: AuthConfiguration.hasAuth, + authType: AuthConfiguration.authType, + certType: AuthConfiguration.certType, + ca: AuthConfiguration.ca, + verificationMode: AuthConfiguration.verificationMode, }; export const ExternalIncidentServiceConfigurationSchema = schema.object( ExternalIncidentServiceConfiguration ); -export const ExternalIncidentServiceSecretConfiguration = { - user: schema.nullable(schema.string()), - password: schema.nullable(schema.string()), -}; - -export const ExternalIncidentServiceSecretConfigurationSchema = schema.object( - ExternalIncidentServiceSecretConfiguration -); - export const ExecutorSubActionPushParamsSchema = schema.object({ incident: schema.object({ title: schema.string(), @@ -93,3 +88,5 @@ export const ExecutorParamsSchema = schema.oneOf([ subActionParams: ExecutorSubActionPushParamsSchema, }), ]); + +export const ExternalIncidentServiceSecretConfigurationSchema = SecretConfigurationSchema; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts index 1e7b492ada959..3a8cf2895e60e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts @@ -9,11 +9,14 @@ import axios, { AxiosError, AxiosResponse } from 'axios'; import { createExternalService } from './service'; import { request, createAxiosResponse } from '@kbn/actions-plugin/server/lib/axios_utils'; -import { CasesWebhookMethods, CasesWebhookPublicConfigurationType, ExternalService } from './types'; +import { CasesWebhookPublicConfigurationType, ExternalService } from './types'; import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { AuthType, WebhookMethods, SSLCertType } from '../../../common/auth/constants'; +import { CRT_FILE, KEY_FILE } from '../../../common/auth/mocks'; + const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { @@ -25,36 +28,51 @@ jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { }); axios.create = jest.fn(() => axios); + const requestMock = request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); const config: CasesWebhookPublicConfigurationType = { createCommentJson: '{"body":{{{case.comment}}}}', - createCommentMethod: CasesWebhookMethods.POST, + createCommentMethod: WebhookMethods.POST, createCommentUrl: 'https://coolsite.net/issue/{{{external.system.id}}}/comment', createIncidentJson: '{"fields":{"title":{{{case.title}}},"description":{{{case.description}}},"tags":{{{case.tags}}},"project":{"key":"ROC"},"issuetype":{"id":"10024"}}}', - createIncidentMethod: CasesWebhookMethods.POST, + createIncidentMethod: WebhookMethods.POST, createIncidentResponseKey: 'id', createIncidentUrl: 'https://coolsite.net/issue', getIncidentResponseExternalTitleKey: 'key', hasAuth: true, - headers: { ['content-type']: 'application/json' }, + headers: { ['content-type']: 'application/json', foo: 'bar' }, viewIncidentUrl: 'https://coolsite.net/browse/{{{external.system.title}}}', getIncidentUrl: 'https://coolsite.net/issue/{{{external.system.id}}}', updateIncidentJson: '{"fields":{"title":{{{case.title}}},"description":{{{case.description}}},"tags":{{{case.tags}}},"project":{"key":"ROC"},"issuetype":{"id":"10024"}}}', - updateIncidentMethod: CasesWebhookMethods.PUT, + updateIncidentMethod: WebhookMethods.PUT, updateIncidentUrl: 'https://coolsite.net/issue/{{{external.system.id}}}', }; const secrets = { user: 'user', password: 'pass', + crt: null, + key: null, + pfx: null, }; +const defaultSSLOverrides = {}; const actionId = '1234'; const mockTime = new Date('2021-10-20T19:41:02.754+0300'); + +const sslConfig: CasesWebhookPublicConfigurationType = { + ...config, + authType: AuthType.SSL, + certType: SSLCertType.CRT, + hasAuth: true, +}; +const sslSecrets = { crt: CRT_FILE, key: KEY_FILE, password: 'foobar', user: null, pfx: null }; + describe('Cases webhook service', () => { let service: ExternalService; + let sslService: ExternalService; beforeAll(() => { service = createExternalService( @@ -66,6 +84,16 @@ describe('Cases webhook service', () => { logger, configurationUtilities ); + + sslService = createExternalService( + actionId, + { + config: sslConfig, + secrets: sslSecrets, + }, + logger, + configurationUtilities + ); jest.useFakeTimers(); jest.setSystemTime(mockTime); }); @@ -98,13 +126,13 @@ describe('Cases webhook service', () => { ).toThrow(); }); - test('throws if hasAuth and no user/pass', () => { + it('throws if hasAuth and no user/pass', () => { expect(() => createExternalService( actionId, { config, - secrets: { user: '', password: '' }, + secrets: { ...secrets, user: '', password: '' }, }, logger, configurationUtilities @@ -112,13 +140,13 @@ describe('Cases webhook service', () => { ).toThrow(); }); - test('does not throw if hasAuth=false and no user/pass', () => { + it('does not throw if hasAuth=false and no user/pass', () => { expect(() => createExternalService( actionId, { config: { ...config, hasAuth: false }, - secrets: { user: '', password: '' }, + secrets: { ...secrets, user: '', password: '' }, }, logger, configurationUtilities @@ -126,12 +154,12 @@ describe('Cases webhook service', () => { ).not.toThrow(); }); - test('uses the basic auth header for authentication', () => { + it('uses the basic auth header for authentication', () => { createExternalService( actionId, { config, - secrets: { user: 'username', password: 'password' }, + secrets: { ...secrets, user: 'username', password: 'password' }, }, logger, configurationUtilities @@ -141,16 +169,17 @@ describe('Cases webhook service', () => { headers: { ...getBasicAuthHeader({ username: 'username', password: 'password' }), 'content-type': 'application/json', + foo: 'bar', }, }); }); - test('does not add the basic auth header for authentication if hasAuth=false', () => { + it('does not add the basic auth header for authentication if hasAuth=false', () => { createExternalService( actionId, { config: { ...config, hasAuth: false }, - secrets: { user: 'username', password: 'password' }, + secrets: { ...secrets, user: 'username', password: 'password' }, }, logger, configurationUtilities @@ -159,6 +188,7 @@ describe('Cases webhook service', () => { expect(axios.create).toHaveBeenCalledWith({ headers: { 'content-type': 'application/json', + foo: 'bar', }, }); }); @@ -176,7 +206,7 @@ describe('Cases webhook service', () => { }, }; - test('it returns the incident correctly', async () => { + it('it returns the incident correctly', async () => { requestMock.mockImplementation(() => createAxiosResponse(axiosRes)); const res = await service.getIncident('1'); expect(res).toEqual({ @@ -185,7 +215,7 @@ describe('Cases webhook service', () => { }); }); - test('it should call request with correct arguments', async () => { + it('it should call request with correct arguments', async () => { requestMock.mockImplementation(() => createAxiosResponse(axiosRes)); await service.getIncident('1'); @@ -194,10 +224,161 @@ describe('Cases webhook service', () => { url: 'https://coolsite.net/issue/1', logger, configurationUtilities, + sslOverrides: defaultSSLOverrides, }); }); - test('it should throw an error', async () => { + it('it should call request with correct arguments when authType=SSL', async () => { + requestMock.mockImplementation(() => createAxiosResponse(axiosRes)); + + await sslService.getIncident('1'); + + // irrelevant snapshot content + delete requestMock.mock.calls[0][0].configurationUtilities; + expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "axios": [Function], + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "sslOverrides": Object { + "cert": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "key": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "passphrase": "foobar", + }, + "url": "https://coolsite.net/issue/1", + } + `); + }); + + it('it should throw an error', async () => { requestMock.mockImplementation(() => { const error: AxiosError = new Error('An error has occurred') as AxiosError; error.response = { statusText: 'Required field' } as AxiosResponse; @@ -208,7 +389,7 @@ describe('Cases webhook service', () => { ); }); - test('it should throw if the request is not a JSON', async () => { + it('it should throw if the request is not a JSON', async () => { requestMock.mockImplementation(() => createAxiosResponse({ ...axiosRes, headers: { ['content-type']: 'text/html' } }) ); @@ -218,7 +399,7 @@ describe('Cases webhook service', () => { ); }); - test('it should throw if the required attributes are not there', async () => { + it('it should throw if the required attributes are not there', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { fields: { notRequired: 'test' } } }) ); @@ -241,7 +422,7 @@ describe('Cases webhook service', () => { }, }; - test('it creates the incident correctly', async () => { + it('it creates the incident correctly', async () => { requestMock.mockImplementationOnce(() => createAxiosResponse({ data: { id: '1', key: 'CK-1', fields: { title: 'title', description: 'description' } }, @@ -271,7 +452,7 @@ describe('Cases webhook service', () => { }); }); - test('it should call request with correct arguments', async () => { + it('it should call request with correct arguments', async () => { requestMock.mockImplementationOnce(() => createAxiosResponse({ data: { @@ -296,13 +477,194 @@ describe('Cases webhook service', () => { axios, url: 'https://coolsite.net/issue', logger, - method: CasesWebhookMethods.POST, + method: WebhookMethods.POST, configurationUtilities, + sslOverrides: defaultSSLOverrides, data: `{"fields":{"title":"title","description":"desc","tags":["hello","world"],"project":{"key":"ROC"},"issuetype":{"id":"10024"}}}`, }); }); - test('it should throw an error', async () => { + it('it should call request with correct arguments when authType=SSL', async () => { + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + }, + }) + ); + + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + }, + }) + ); + + await sslService.createIncident(incident); + + // irrelevant snapshot content + delete requestMock.mock.calls[0][0].configurationUtilities; + expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "axios": [Function], + "data": "{\\"fields\\":{\\"title\\":\\"title\\",\\"description\\":\\"desc\\",\\"tags\\":[\\"hello\\",\\"world\\"],\\"project\\":{\\"key\\":\\"ROC\\"},\\"issuetype\\":{\\"id\\":\\"10024\\"}}}", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"1234\\": [HTTP 200] OK", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "method": "post", + "sslOverrides": Object { + "cert": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "key": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "passphrase": "foobar", + }, + "url": "https://coolsite.net/issue", + } + `); + }); + + it('it should throw an error', async () => { requestMock.mockImplementation(() => { const error: AxiosError = new Error('An error has occurred') as AxiosError; error.response = { statusText: 'Required field' } as AxiosResponse; @@ -314,7 +676,7 @@ describe('Cases webhook service', () => { ); }); - test('it should throw if the request is not a JSON', async () => { + it('it should throw if the request is not a JSON', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) ); @@ -324,7 +686,7 @@ describe('Cases webhook service', () => { ); }); - test('it should throw if the required attributes are not there', async () => { + it('it should throw if the required attributes are not there', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); await expect(service.createIncident(incident)).rejects.toThrow( @@ -346,7 +708,7 @@ describe('Cases webhook service', () => { }, }; - test('it updates the incident correctly', async () => { + it('it updates the incident correctly', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { @@ -366,7 +728,7 @@ describe('Cases webhook service', () => { }); }); - test('it should call request with correct arguments', async () => { + it('it should call request with correct arguments', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { @@ -381,8 +743,9 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toEqual({ axios, logger, - method: CasesWebhookMethods.PUT, + method: WebhookMethods.PUT, configurationUtilities, + sslOverrides: defaultSSLOverrides, url: 'https://coolsite.net/issue/1', data: JSON.stringify({ fields: { @@ -396,7 +759,166 @@ describe('Cases webhook service', () => { }); }); - test('it should throw an error', async () => { + it('it should call request with correct arguments when authType=SSL', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + }, + }) + ); + + await sslService.updateIncident(incident); + + // irrelevant snapshot content + delete requestMock.mock.calls[0][0].configurationUtilities; + expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "axios": [Function], + "data": "{\\"fields\\":{\\"title\\":\\"title\\",\\"description\\":\\"desc\\",\\"tags\\":[\\"hello\\",\\"world\\"],\\"project\\":{\\"key\\":\\"ROC\\"},\\"issuetype\\":{\\"id\\":\\"10024\\"}}}", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "method": "put", + "sslOverrides": Object { + "cert": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "key": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "passphrase": "foobar", + }, + "url": "https://coolsite.net/issue/1", + } + `); + }); + + it('it should throw an error', async () => { requestMock.mockImplementation(() => { const error: AxiosError = new Error('An error has occurred') as AxiosError; error.response = { statusText: 'Required field' } as AxiosResponse; @@ -408,7 +930,7 @@ describe('Cases webhook service', () => { ); }); - test('it should throw if the request is not a JSON', async () => { + it('it should throw if the request is not a JSON', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) ); @@ -427,7 +949,7 @@ describe('Cases webhook service', () => { commentId: 'comment-1', }, }; - test('it creates the comment correctly', async () => { + it('it creates the comment correctly', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { @@ -442,7 +964,7 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0].data).toEqual('{"body":"comment"}'); }); - test('it should call request with correct arguments', async () => { + it('it should call request with correct arguments', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { @@ -457,14 +979,174 @@ describe('Cases webhook service', () => { expect(requestMock).toHaveBeenCalledWith({ axios, logger, - method: CasesWebhookMethods.POST, + method: WebhookMethods.POST, configurationUtilities, + sslOverrides: defaultSSLOverrides, url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment"}`, }); }); - test('it should throw an error', async () => { + it('it should call request with correct arguments when authType=SSL', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + }, + }) + ); + + await sslService.createComment(commentReq); + + // irrelevant snapshot content + delete requestMock.mock.calls[0][0].configurationUtilities; + expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "axios": [Function], + "data": "{\\"body\\":\\"comment\\"}", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "method": "post", + "sslOverrides": Object { + "cert": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 67, + 69, + 82, + 84, + 73, + 70, + 73, + 67, + 65, + 84, + 69, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "key": Object { + "data": Array [ + 10, + 45, + 45, + 45, + 45, + 45, + 66, + 69, + 71, + 73, + 78, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + 45, + 45, + 45, + 45, + 45, + 69, + 78, + 68, + 32, + 80, + 82, + 73, + 86, + 65, + 84, + 69, + 32, + 75, + 69, + 89, + 45, + 45, + 45, + 45, + 45, + 10, + ], + "type": "Buffer", + }, + "passphrase": "foobar", + }, + "url": "https://coolsite.net/issue/1/comment", + } + `); + }); + + it('it should throw an error', async () => { requestMock.mockImplementation(() => { const error: AxiosError = new Error('An error has occurred') as AxiosError; error.response = { statusText: 'Required field' } as AxiosResponse; @@ -476,7 +1158,7 @@ describe('Cases webhook service', () => { ); }); - test('it should throw if the request is not a JSON', async () => { + it('it should throw if the request is not a JSON', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) ); @@ -486,7 +1168,7 @@ describe('Cases webhook service', () => { ); }); - test('it fails silently if createCommentUrl is missing', async () => { + it('it fails silently if createCommentUrl is missing', async () => { service = createExternalService( actionId, { @@ -501,7 +1183,7 @@ describe('Cases webhook service', () => { expect(res).toBeUndefined(); }); - test('it fails silently if createCommentJson is missing', async () => { + it('it fails silently if createCommentJson is missing', async () => { service = createExternalService( actionId, { @@ -516,7 +1198,7 @@ describe('Cases webhook service', () => { expect(res).toBeUndefined(); }); - test('properly encodes external system id as string in request body', async () => { + it('properly encodes external system id as string in request body', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { @@ -541,14 +1223,15 @@ describe('Cases webhook service', () => { expect(requestMock).toHaveBeenCalledWith({ axios, logger, - method: CasesWebhookMethods.POST, + method: WebhookMethods.POST, configurationUtilities, url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment","id":"1"}`, + sslOverrides: defaultSSLOverrides, }); }); - test('properly encodes external system id as number in request body', async () => { + it('properly encodes external system id as number in request body', async () => { const commentReq2 = { incidentId: 1 as unknown as string, comment: { @@ -580,10 +1263,11 @@ describe('Cases webhook service', () => { expect(requestMock).toHaveBeenCalledWith({ axios, logger, - method: CasesWebhookMethods.POST, + method: WebhookMethods.POST, configurationUtilities, url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment","id":1}`, + sslOverrides: defaultSSLOverrides, }); }); }); @@ -609,12 +1293,12 @@ describe('Cases webhook service', () => { beforeEach(() => { jest.clearAllMocks(); }); - test('getIncident- throws for bad url', async () => { + it('getIncident- throws for bad url', async () => { await expect(service.getIncident('whack')).rejects.toThrow( '[Action][Webhook - Case Management]: Unable to get case with id whack. Error: Invalid Get case URL: Error: error configuring connector action: Uri not allowed.' ); }); - test('createIncident- throws for bad url', async () => { + it('createIncident- throws for bad url', async () => { const incident = { incident: { title: 'title', @@ -630,7 +1314,7 @@ describe('Cases webhook service', () => { '[Action][Webhook - Case Management]: Unable to create case. Error: Invalid Create case URL: Error: error configuring connector action: Uri not allowed.' ); }); - test('updateIncident- throws for bad url', async () => { + it('updateIncident- throws for bad url', async () => { const incident = { incidentId: '123', incident: { @@ -647,7 +1331,7 @@ describe('Cases webhook service', () => { '[Action][Webhook - Case Management]: Unable to update case with id 123. Error: Invalid Update case URL: Error: error configuring connector action: Uri not allowed.' ); }); - test('createComment- throws for bad url', async () => { + it('createComment- throws for bad url', async () => { const commentReq = { incidentId: '1', comment: { @@ -683,12 +1367,12 @@ describe('Cases webhook service', () => { beforeEach(() => { jest.clearAllMocks(); }); - test('getIncident- throws for bad protocol', async () => { + it('getIncident- throws for bad protocol', async () => { await expect(service.getIncident('whack')).rejects.toThrow( '[Action][Webhook - Case Management]: Unable to get case with id whack. Error: Invalid Get case URL: Error: Invalid protocol.' ); }); - test('createIncident- throws for bad protocol', async () => { + it('createIncident- throws for bad protocol', async () => { const incident = { incident: { title: 'title', @@ -704,7 +1388,7 @@ describe('Cases webhook service', () => { '[Action][Webhook - Case Management]: Unable to create case. Error: Invalid Create case URL: Error: Invalid protocol.' ); }); - test('updateIncident- throws for bad protocol', async () => { + it('updateIncident- throws for bad protocol', async () => { const incident = { incidentId: '123', incident: { @@ -721,7 +1405,7 @@ describe('Cases webhook service', () => { '[Action][Webhook - Case Management]: Unable to update case with id 123. Error: Invalid Update case URL: Error: Invalid protocol.' ); }); - test('createComment- throws for bad protocol', async () => { + it('createComment- throws for bad protocol', async () => { const commentReq = { incidentId: '1', comment: { @@ -761,14 +1445,14 @@ describe('Cases webhook service', () => { beforeEach(() => { jest.clearAllMocks(); }); - test('getIncident- escapes url', async () => { + it('getIncident- escapes url', async () => { await service.getIncident('../../malicious-app/malicious-endpoint/'); expect(requestMock.mock.calls[0][0].url).toEqual( 'https://coolsite.net/issue/..%2F..%2Fmalicious-app%2Fmalicious-endpoint%2F' ); }); - test('createIncident- escapes url', async () => { + it('createIncident- escapes url', async () => { const incident = { incident: { title: 'title', @@ -785,7 +1469,7 @@ describe('Cases webhook service', () => { ); }); - test('updateIncident- escapes url', async () => { + it('updateIncident- escapes url', async () => { const incident = { incidentId: '../../malicious-app/malicious-endpoint/', incident: { @@ -803,7 +1487,7 @@ describe('Cases webhook service', () => { 'https://coolsite.net/issue/..%2F..%2Fmalicious-app%2Fmalicious-endpoint%2F' ); }); - test('createComment- escapes url', async () => { + it('createComment- escapes url', async () => { const commentReq = { incidentId: '../../malicious-app/malicious-endpoint/', comment: { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts index 46407c18bd081..424fe9b394517 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts @@ -12,6 +12,7 @@ import { renderMustacheStringNoEscape } from '@kbn/actions-plugin/server/lib/mus import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { buildConnectorAuth, validateConnectorAuthConfiguration } from '../../../common/auth/utils'; import { validateAndNormalizeUrl, validateJson } from './validators'; import { createServiceError, @@ -20,12 +21,11 @@ import { removeSlash, throwDescriptiveErrorIfResponseIsNotValid, } from './utils'; -import { +import type { CreateIncidentParams, ExternalServiceCredentials, ExternalService, CasesWebhookPublicConfigurationType, - CasesWebhookSecretConfigurationType, ExternalServiceIncidentResponse, GetIncidentResponse, UpdateIncidentParams, @@ -51,31 +51,41 @@ export const createExternalService = ( getIncidentResponseExternalTitleKey, getIncidentUrl, hasAuth, + authType, headers, viewIncidentUrl, updateIncidentJson, updateIncidentMethod, updateIncidentUrl, + verificationMode, + ca, } = config as CasesWebhookPublicConfigurationType; - const { password, user } = secrets as CasesWebhookSecretConfigurationType; - if ( - !getIncidentUrl || - !createIncidentUrlConfig || - !viewIncidentUrl || - !updateIncidentUrl || - (hasAuth && (!password || !user)) - ) { + + const { basicAuth, sslOverrides } = buildConnectorAuth({ + hasAuth, + authType, + secrets, + verificationMode, + ca, + }); + + validateConnectorAuthConfiguration({ + hasAuth, + authType, + basicAuth, + sslOverrides, + connectorName: i18n.NAME, + }); + + if (!getIncidentUrl || !createIncidentUrlConfig || !viewIncidentUrl || !updateIncidentUrl) { throw Error(`[Action]${i18n.NAME}: Wrong configuration.`); } - const createIncidentUrl = removeSlash(createIncidentUrlConfig); - const headersWithBasicAuth = hasAuth - ? combineHeadersWithBasicAuthHeader({ - username: user ?? undefined, - password: password ?? undefined, - headers, - }) - : {}; + const headersWithBasicAuth = combineHeadersWithBasicAuthHeader({ + username: basicAuth.auth?.username, + password: basicAuth.auth?.password, + headers, + }); const axiosInstance = axios.create({ headers: { @@ -84,6 +94,8 @@ export const createExternalService = ( }, }); + const createIncidentUrl = removeSlash(createIncidentUrlConfig); + const getIncident = async (id: string): Promise => { try { const getUrl = renderMustacheStringNoEscape(getIncidentUrl, { @@ -104,6 +116,7 @@ export const createExternalService = ( url: normalizedUrl, logger, configurationUtilities, + sslOverrides, }); throwDescriptiveErrorIfResponseIsNotValid({ @@ -148,6 +161,7 @@ export const createExternalService = ( method: createIncidentMethod, data: json, configurationUtilities, + sslOverrides, }); const { status, statusText, data } = res; @@ -231,6 +245,7 @@ export const createExternalService = ( logger, data: json, configurationUtilities, + sslOverrides, }); throwDescriptiveErrorIfResponseIsNotValid({ @@ -303,6 +318,7 @@ export const createExternalService = ( logger, data: json, configurationUtilities, + sslOverrides, }); throwDescriptiveErrorIfResponseIsNotValid({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/translations.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/translations.ts index a3180e6cca663..188c4516d22a3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/translations.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/translations.ts @@ -28,12 +28,9 @@ export const CONFIG_ERR = (err: string) => }, }); -export const INVALID_USER_PW = i18n.translate( - 'xpack.stackConnectors.casesWebhook.invalidUsernamePassword', - { - defaultMessage: 'both user and password must be specified', - } -); +export const INVALID_AUTH = i18n.translate('xpack.stackConnectors.casesWebhook.invalidSecrets', { + defaultMessage: 'must specify a secrets configuration', +}); export const ALLOWED_HOSTS_ERROR = (message: string) => i18n.translate('xpack.stackConnectors.casesWebhook.configuration.apiAllowedHostsError', { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/types.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/types.ts index c4404748fc33b..95af6d5e306f2 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/types.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/types.ts @@ -7,7 +7,6 @@ import { TypeOf } from '@kbn/config-schema'; import { Logger } from '@kbn/core/server'; -import { ValidatorServices } from '@kbn/actions-plugin/server/types'; import { ExecutorParamsSchema, ExecutorSubActionPushParamsSchema, @@ -15,13 +14,6 @@ import { ExternalIncidentServiceSecretConfigurationSchema, } from './schema'; -// config definition -export enum CasesWebhookMethods { - PATCH = 'patch', - POST = 'post', - PUT = 'put', -} - // config export type CasesWebhookPublicConfigurationType = TypeOf< typeof ExternalIncidentServiceConfigurationSchema @@ -38,21 +30,6 @@ export interface ExternalServiceCredentials { secrets: CasesWebhookSecretConfigurationType; } -export interface ExternalServiceValidation { - config: ( - configObject: CasesWebhookPublicConfigurationType, - validatorServices: ValidatorServices - ) => void; - secrets: ( - secrets: CasesWebhookSecretConfigurationType, - validatorServices: ValidatorServices - ) => void; - connector: ( - configObject: CasesWebhookPublicConfigurationType, - secrets: CasesWebhookSecretConfigurationType - ) => string | null; -} - export interface ExternalServiceIncidentResponse { id: string; title: string; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/validators.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/validators.ts index 95265cfcaf6ef..21922d608156e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/validators.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/validators.ts @@ -7,14 +7,11 @@ import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { ValidatorServices } from '@kbn/actions-plugin/server/types'; +import { isEmpty } from 'lodash'; import * as i18n from './translations'; -import { - CasesWebhookPublicConfigurationType, - CasesWebhookSecretConfigurationType, - ExternalServiceValidation, -} from './types'; +import { CasesWebhookPublicConfigurationType, CasesWebhookSecretConfigurationType } from './types'; -const validateConfig = ( +export const validateCasesWebhookConfig = ( configObject: CasesWebhookPublicConfigurationType, validatorServices: ValidatorServices ) => { @@ -55,26 +52,8 @@ export const validateConnector = ( configObject: CasesWebhookPublicConfigurationType, secrets: CasesWebhookSecretConfigurationType ): string | null => { - // user and password must be set together (or not at all) - if (!configObject.hasAuth) return null; - if (secrets.password && secrets.user) return null; - return i18n.INVALID_USER_PW; -}; - -export const validateSecrets = ( - secrets: CasesWebhookSecretConfigurationType, - validatorServices: ValidatorServices -) => { - // user and password must be set together (or not at all) - if (!secrets.password && !secrets.user) return; - if (secrets.password && secrets.user) return; - throw new Error(i18n.INVALID_USER_PW); -}; - -export const validate: ExternalServiceValidation = { - config: validateConfig, - secrets: validateSecrets, - connector: validateConnector, + if (configObject.hasAuth && isEmpty(secrets)) return i18n.INVALID_AUTH; + return null; }; const validProtocols: string[] = ['http:', 'https:']; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/index.ts index 04c7004f7325b..6364fed0e193f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/index.ts @@ -58,7 +58,7 @@ export type { SlackApiActionParams as SlackApiActionParams } from '../../common/ export { ConnectorTypeId as TeamsConnectorTypeId } from './teams'; export type { ActionParamsType as TeamsActionParams } from './teams'; export { ConnectorTypeId as WebhookConnectorTypeId } from './webhook'; -export type { ActionParamsType as WebhookActionParams } from './webhook'; +export type { ActionParamsType as WebhookActionParams } from './webhook/types'; export { ConnectorTypeId as XmattersConnectorTypeId } from './xmatters'; export type { ActionParamsType as XmattersActionParams } from './xmatters'; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/nullable.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/nullable.ts deleted file mode 100644 index af95e728465da..0000000000000 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/nullable.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema, Type } from '@kbn/config-schema'; - -// TODO: remove once this is merged: https://github.com/elastic/kibana/pull/41728 - -export function nullableType(type: Type) { - return schema.oneOf([type, schema.literal(null)], { defaultValue: () => null }); -} diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts index 9e82b2d2c31e7..6c51fe11e97de 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts @@ -12,18 +12,14 @@ import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/action import { Logger } from '@kbn/core/server'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import axios from 'axios'; -import { - ConnectorTypeConfigType, - ConnectorTypeSecretsType, - getConnectorType, - WebhookConnectorType, - WebhookMethods, -} from '.'; +import { ConnectorTypeConfigType, ConnectorTypeSecretsType, WebhookConnectorType } from './types'; + +import { getConnectorType } from '.'; import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; import { loggerMock } from '@kbn/logging-mocks'; -import { SSLCertType, WebhookAuthType } from '../../../common/webhook/constants'; -import { PFX_FILE, CRT_FILE, KEY_FILE } from './mocks'; +import { AuthType, SSLCertType, WebhookMethods } from '../../../common/auth/constants'; +import { PFX_FILE, CRT_FILE, KEY_FILE } from '../../../common/auth/mocks'; jest.mock('axios'); jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { @@ -157,7 +153,7 @@ describe('config validation', () => { test('config validation passes when only required fields are provided', () => { const config: Record = { url: 'http://mylisteningserver:9200/endpoint', - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; expect(validateConfig(connectorType, config, { configurationUtilities })).toEqual({ @@ -171,7 +167,7 @@ describe('config validation', () => { const config: Record = { url: 'http://mylisteningserver:9200/endpoint', method, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; expect(validateConfig(connectorType, config, { configurationUtilities })).toEqual({ @@ -198,7 +194,7 @@ describe('config validation', () => { test('config validation passes when a url is specified', () => { const config: Record = { url: 'http://mylisteningserver:9200/endpoint', - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; expect(validateConfig(connectorType, config, { configurationUtilities })).toEqual({ @@ -226,7 +222,7 @@ describe('config validation', () => { headers: { 'Content-Type': 'application/json', }, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; expect(validateConfig(connectorType, config, { configurationUtilities })).toEqual({ @@ -257,7 +253,7 @@ describe('config validation', () => { headers: { 'Content-Type': 'application/json', }, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; @@ -332,7 +328,7 @@ describe('execute()', () => { headers: { aheader: 'a value', }, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; await connectorType.executor({ @@ -392,7 +388,7 @@ describe('execute()', () => { headers: { aheader: 'a value', }, - authType: WebhookAuthType.SSL, + authType: AuthType.SSL, certType: SSLCertType.CRT, hasAuth: true, }; @@ -575,7 +571,7 @@ describe('execute()', () => { headers: { aheader: 'a value', }, - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, }; requestMock.mockReset(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts index c5314f8e5f7ad..78f02d24b9b87 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts @@ -6,18 +6,16 @@ */ import { i18n } from '@kbn/i18n'; -import { isString } from 'lodash'; import axios, { AxiosError, AxiosResponse } from 'axios'; -import { schema, TypeOf } from '@kbn/config-schema'; import { Logger } from '@kbn/core/server'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, getOrElse } from 'fp-ts/lib/Option'; + import type { - ActionType as ConnectorType, - ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, ActionTypeExecutorResult as ConnectorTypeExecutorResult, ValidatorServices, } from '@kbn/actions-plugin/server/types'; + import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { AlertingConnectorFeatureId, @@ -26,90 +24,23 @@ import { } from '@kbn/actions-plugin/common/types'; import { renderMustacheString } from '@kbn/actions-plugin/server/lib/mustache_renderer'; import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; -import { SSLCertType, WebhookAuthType } from '../../../common/webhook/constants'; -import { getRetryAfterIntervalFromHeaders } from '../lib/http_response_retry_header'; -import { nullableType } from '../lib/nullable'; -import { isOk, promiseResult, Result } from '../lib/result_type'; - -// config definition -export enum WebhookMethods { - POST = 'post', - PUT = 'put', -} -export type WebhookConnectorType = ConnectorType< - ConnectorTypeConfigType, - ConnectorTypeSecretsType, +import type { + WebhookConnectorType, ActionParamsType, - unknown ->; -export type WebhookConnectorTypeExecutorOptions = ConnectorTypeExecutorOptions< ConnectorTypeConfigType, + WebhookConnectorTypeExecutorOptions, ConnectorTypeSecretsType, - ActionParamsType ->; +} from './types'; -const HeadersSchema = schema.recordOf(schema.string(), schema.string()); -const configSchemaProps = { - url: schema.string(), - method: schema.oneOf([schema.literal(WebhookMethods.POST), schema.literal(WebhookMethods.PUT)], { - defaultValue: WebhookMethods.POST, - }), - headers: nullableType(HeadersSchema), - hasAuth: schema.boolean({ defaultValue: true }), - authType: schema.maybe( - schema.oneOf( - [ - schema.literal(WebhookAuthType.Basic), - schema.literal(WebhookAuthType.SSL), - schema.literal(null), - ], - { - defaultValue: WebhookAuthType.Basic, - } - ) - ), - certType: schema.maybe( - schema.oneOf([schema.literal(SSLCertType.CRT), schema.literal(SSLCertType.PFX)]) - ), - ca: schema.maybe(schema.string()), - verificationMode: schema.maybe( - schema.oneOf([schema.literal('none'), schema.literal('certificate'), schema.literal('full')]) - ), -}; -const ConfigSchema = schema.object(configSchemaProps); -export type ConnectorTypeConfigType = TypeOf; - -// secrets definition -export type ConnectorTypeSecretsType = TypeOf; -const secretSchemaProps = { - user: schema.nullable(schema.string()), - password: schema.nullable(schema.string()), - crt: schema.nullable(schema.string()), - key: schema.nullable(schema.string()), - pfx: schema.nullable(schema.string()), -}; -const SecretsSchema = schema.object(secretSchemaProps, { - validate: (secrets) => { - // user and password must be set together (or not at all) - if (!secrets.password && !secrets.user && !secrets.crt && !secrets.key && !secrets.pfx) return; - if (secrets.password && secrets.user && !secrets.crt && !secrets.key && !secrets.pfx) return; - if (secrets.crt && secrets.key && !secrets.user && !secrets.pfx) return; - if (!secrets.crt && !secrets.key && !secrets.user && secrets.pfx) return; - return i18n.translate('xpack.stackConnectors.webhook.invalidUsernamePassword', { - defaultMessage: - 'must specify one of the following schemas: user and password; crt and key (with optional password); or pfx (with optional password)', - }); - }, -}); - -// params definition -export type ActionParamsType = TypeOf; -export const ParamsSchema = schema.object({ - body: schema.maybe(schema.string()), -}); +import { getRetryAfterIntervalFromHeaders } from '../lib/http_response_retry_header'; +import { isOk, promiseResult, Result } from '../lib/result_type'; +import { ConfigSchema, ParamsSchema } from './schema'; +import { buildConnectorAuth } from '../../../common/auth/utils'; +import { SecretConfigurationSchema } from '../../../common/auth/schema'; export const ConnectorTypeId = '.webhook'; + // connector type definition export function getConnectorType(): WebhookConnectorType { return { @@ -129,7 +60,7 @@ export function getConnectorType(): WebhookConnectorType { customValidator: validateConnectorTypeConfig, }, secrets: { - schema: SecretsSchema, + schema: SecretConfigurationSchema, }, params: { schema: ParamsSchema, @@ -202,39 +133,16 @@ export async function executor( const { body: data } = params; const secrets: ConnectorTypeSecretsType = execOptions.secrets; - // For backwards compatibility with connectors created before authType was added, interpret a - // hasAuth: true and undefined authType as basic auth - const basicAuth = - hasAuth && - (authType === WebhookAuthType.Basic || !authType) && - isString(secrets.user) && - isString(secrets.password) - ? { auth: { username: secrets.user, password: secrets.password } } - : {}; - - const sslCertificate = - authType === WebhookAuthType.SSL && - ((isString(secrets.crt) && isString(secrets.key)) || isString(secrets.pfx)) - ? isString(secrets.pfx) - ? { - pfx: Buffer.from(secrets.pfx, 'base64'), - ...(isString(secrets.password) ? { passphrase: secrets.password } : {}), - } - : { - cert: Buffer.from(secrets.crt!, 'base64'), - key: Buffer.from(secrets.key!, 'base64'), - ...(isString(secrets.password) ? { passphrase: secrets.password } : {}), - } - : {}; + const { basicAuth, sslOverrides } = buildConnectorAuth({ + hasAuth, + authType, + secrets, + verificationMode, + ca, + }); const axiosInstance = axios.create(); - const sslOverrides = { - ...sslCertificate, - ...(verificationMode ? { verificationMode } : {}), - ...(ca ? { ca: Buffer.from(ca, 'base64') } : {}), - }; - const headersWithBasicAuth = combineHeadersWithBasicAuthHeader({ username: basicAuth.auth?.username, password: basicAuth.auth?.password, diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/schema.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/schema.ts new file mode 100644 index 0000000000000..b6eca5de787f3 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/schema.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { AuthConfiguration } from '../../../common/auth/schema'; +import { WebhookMethods } from '../../../common/auth/constants'; + +export const HeadersSchema = schema.recordOf(schema.string(), schema.string()); + +const configSchemaProps = { + url: schema.string(), + method: schema.oneOf([schema.literal(WebhookMethods.POST), schema.literal(WebhookMethods.PUT)], { + defaultValue: WebhookMethods.POST, + }), + headers: schema.nullable(HeadersSchema), + hasAuth: AuthConfiguration.hasAuth, + authType: AuthConfiguration.authType, + certType: AuthConfiguration.certType, + ca: AuthConfiguration.ca, + verificationMode: AuthConfiguration.verificationMode, +}; + +export const ConfigSchema = schema.object(configSchemaProps); + +// params definition +export const ParamsSchema = schema.object({ + body: schema.maybe(schema.string()), +}); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/types.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/types.ts new file mode 100644 index 0000000000000..4857a88f2a042 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TypeOf } from '@kbn/config-schema'; +import type { + ActionType as ConnectorType, + ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, +} from '@kbn/actions-plugin/server/types'; +import { ParamsSchema, ConfigSchema } from './schema'; +import { SecretConfigurationSchema } from '../../../common/auth/schema'; + +export type WebhookConnectorType = ConnectorType< + ConnectorTypeConfigType, + ConnectorTypeSecretsType, + ActionParamsType, + unknown +>; +export type WebhookConnectorTypeExecutorOptions = ConnectorTypeExecutorOptions< + ConnectorTypeConfigType, + ConnectorTypeSecretsType, + ActionParamsType +>; + +export type ConnectorTypeConfigType = TypeOf; + +// secrets definition +export type ConnectorTypeSecretsType = TypeOf; + +// params definition +export type ActionParamsType = TypeOf; diff --git a/x-pack/plugins/stack_connectors/server/index.ts b/x-pack/plugins/stack_connectors/server/index.ts index 0069036c4ea83..38fc3b3297c58 100644 --- a/x-pack/plugins/stack_connectors/server/index.ts +++ b/x-pack/plugins/stack_connectors/server/index.ts @@ -10,7 +10,7 @@ import { SlackApiParamsSchema } from '../common/slack_api/schema'; export { ParamsSchema as SlackParamsSchema } from './connector_types/slack'; export { ParamsSchema as EmailParamsSchema } from './connector_types/email'; -export { ParamsSchema as WebhookParamsSchema } from './connector_types/webhook'; +export { ParamsSchema as WebhookParamsSchema } from './connector_types/webhook/schema'; export { ExecutorParamsSchema as JiraParamsSchema } from './connector_types/jira/schema'; export { ParamsSchema as PagerdutyParamsSchema } from './connector_types/pagerduty'; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index eec216c68d584..fd47cd081f878 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -39312,7 +39312,6 @@ "xpack.stackConnectors.xmatters.invalidUrlError": "secretsUrl non valide : {err}", "xpack.stackConnectors.xmatters.postingRetryErrorMessage": "Erreur lors du déclenchement du flux xMatters : statut http {status}, réessayer plus tard", "xpack.stackConnectors.xmatters.unexpectedStatusErrorMessage": "Erreur de déclenchement du flux xMatters : statut inattendu {status}", - "xpack.stackConnectors.casesWebhook.invalidUsernamePassword": "l'utilisateur et le mot de passe doivent être spécifiés", "xpack.stackConnectors.casesWebhook.title": "Webhook - Gestion des cas", "xpack.stackConnectors.components.bedrock.accessKeySecret": "Clé d'accès", "xpack.stackConnectors.components.bedrock.apiUrlTextFieldLabel": "URL", @@ -39327,9 +39326,7 @@ "xpack.stackConnectors.components.bedrock.selectMessageText": "Envoyer une requête à Amazon Bedrock.", "xpack.stackConnectors.components.bedrock.title": "Amazon Bedrock", "xpack.stackConnectors.components.bedrock.urlTextFieldLabel": "URL", - "xpack.stackConnectors.components.casesWebhook.addHeaderButton": "Ajouter", "xpack.stackConnectors.components.casesWebhook.addVariable": "Ajouter une variable", - "xpack.stackConnectors.components.casesWebhook.authenticationLabel": "Authentification", "xpack.stackConnectors.components.casesWebhook.caseCommentDesc": "Commentaire de cas Kibana", "xpack.stackConnectors.components.casesWebhook.caseDescriptionDesc": "Description de cas Kibana", "xpack.stackConnectors.components.casesWebhook.caseIdDesc": "ID de cas Kibana", @@ -39352,11 +39349,8 @@ "xpack.stackConnectors.components.casesWebhook.createIncidentResponseKeyTextFieldLabel": "Clé externe dans la réponse de création d'un cas", "xpack.stackConnectors.components.casesWebhook.createIncidentUrlTextFieldLabel": "URL de création d'un cas", "xpack.stackConnectors.components.casesWebhook.criticalLabel": "Critique", - "xpack.stackConnectors.components.casesWebhook.deleteHeaderButton": "Supprimer", "xpack.stackConnectors.components.casesWebhook.descriptionTextAreaFieldLabel": "Description", "xpack.stackConnectors.components.casesWebhook.docLink": "Configuration de Webhook - Connecteur de gestion des cas.", - "xpack.stackConnectors.components.casesWebhook.error.requiredAuthPasswordText": "Le mot de passe est requis.", - "xpack.stackConnectors.components.casesWebhook.error.requiredAuthUserNameText": "Le nom d'utilisateur est requis.", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentIncidentText": "L'objet de création de commentaire doit être un JSON valide.", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentMethodText": "La méthode de création de commentaire est requise.", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentUrlText": "L'URL de création de commentaire doit être au format URL.", @@ -39381,15 +39375,12 @@ "xpack.stackConnectors.components.casesWebhook.getIncidentUrlTextFieldLabel": "URL d'obtention de cas", "xpack.stackConnectors.components.casesWebhook.hasAuthSwitchLabel": "Demander une authentification pour ce webhook", "xpack.stackConnectors.components.casesWebhook.highLabel": "Élevé", - "xpack.stackConnectors.components.casesWebhook.httpHeadersTitle": "En-têtes utilisés", "xpack.stackConnectors.components.casesWebhook.idFieldLabel": "ID de cas", "xpack.stackConnectors.components.casesWebhook.jsonCodeEditorAriaLabel": "Éditeur de code", "xpack.stackConnectors.components.casesWebhook.jsonFieldLabel": "JSON", - "xpack.stackConnectors.components.casesWebhook.keyTextFieldLabel": "Clé", "xpack.stackConnectors.components.casesWebhook.lowLabel": "Bas", "xpack.stackConnectors.components.casesWebhook.mediumLabel": "Moyenne", "xpack.stackConnectors.components.casesWebhook.next": "Suivant", - "xpack.stackConnectors.components.casesWebhook.passwordTextFieldLabel": "Mot de passe", "xpack.stackConnectors.components.casesWebhook.previous": "Précédent", "xpack.stackConnectors.components.casesWebhook.selectMessageText": "Envoyer une requête à un service web de gestion de cas.", "xpack.stackConnectors.components.casesWebhook.severityFieldLabel": "Sévérité", @@ -39414,9 +39405,6 @@ "xpack.stackConnectors.components.casesWebhook.updateIncidentMethodTextFieldLabel": "Méthode de mise à jour de cas", "xpack.stackConnectors.components.casesWebhook.updateIncidentUrlHelp": "URL d'API pour mettre à jour un cas.", "xpack.stackConnectors.components.casesWebhook.updateIncidentUrlTextFieldLabel": "URL de mise à jour du cas", - "xpack.stackConnectors.components.casesWebhook.userTextFieldLabel": "Nom d'utilisateur", - "xpack.stackConnectors.components.casesWebhook.valueTextFieldLabel": "Valeur", - "xpack.stackConnectors.components.casesWebhook.viewHeadersSwitch": "Ajouter un en-tête HTTP", "xpack.stackConnectors.components.casesWebhook.viewIncidentUrlHelp": "URL pour afficher un cas dans le système externe. Utilisez le sélecteur de variable pour ajouter à l'URL l'ID ou le titre du système externe.", "xpack.stackConnectors.components.casesWebhook.viewIncidentUrlTextFieldLabel": "URL de visualisation de cas externe", "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - Données de gestion des cas", @@ -39766,39 +39754,15 @@ "xpack.stackConnectors.components.teams.messageTextAreaFieldLabel": "Message", "xpack.stackConnectors.components.teams.selectMessageText": "Envoyer un message à un canal Microsoft Teams.", "xpack.stackConnectors.components.teams.webhookUrlHelpLabel": "Créer une URL de webhook Microsoft Teams", - "xpack.stackConnectors.components.webhook.addHeaderButtonLabel": "Ajouter un en-tête", - "xpack.stackConnectors.components.webhook.authenticationLabel": "Authentification", - "xpack.stackConnectors.components.webhook.authenticationMethodBasicLabel": "Authentification de base", - "xpack.stackConnectors.components.webhook.authenticationMethodNoneLabel": "Aucun", - "xpack.stackConnectors.components.webhook.authenticationMethodSSLLabel": "Authentification SSL", "xpack.stackConnectors.components.webhook.bodyCodeEditorAriaLabel": "Éditeur de code", "xpack.stackConnectors.components.webhook.bodyFieldLabel": "Corps", - "xpack.stackConnectors.components.webhook.certTypeCrtKeyLabel": "Fichier CRT et KEY", - "xpack.stackConnectors.components.webhook.certTypePfxLabel": "Fichier PFX", "xpack.stackConnectors.components.webhook.connectorTypeTitle": "Données de webhook", - "xpack.stackConnectors.components.webhook.editCACallout": "Ce webhook comporte déjà un fichier d'autorité de certificat. Charger un nouveau pour le remplacer.", "xpack.stackConnectors.components.webhook.error.invalidUrlTextField": "L'URL n'est pas valide.", - "xpack.stackConnectors.components.webhook.error.requiredAuthUserNameText": "Le nom d'utilisateur est requis.", "xpack.stackConnectors.components.webhook.error.requiredMethodText": "La méthode est requise.", "xpack.stackConnectors.components.webhook.error.requiredWebhookBodyText": "Le corps est requis.", - "xpack.stackConnectors.components.webhook.error.requiredWebhookCAText": "Le fichier CA est requis.", - "xpack.stackConnectors.components.webhook.error.requiredWebhookCRTText": "Le fichier CRT est requis.", - "xpack.stackConnectors.components.webhook.error.requiredWebhookKEYText": "Le fichier KEY est requis.", - "xpack.stackConnectors.components.webhook.error.requiredWebhookPasswordText": "Le mot de passe est requis.", - "xpack.stackConnectors.components.webhook.error.requiredWebhookPFXText": "Le fichier PFX est requis.", - "xpack.stackConnectors.components.webhook.hasAuthSwitchLabel": "Demander une authentification pour ce webhook", - "xpack.stackConnectors.components.webhook.headerKeyTextFieldLabel": "Clé", - "xpack.stackConnectors.components.webhook.headerValueTextFieldLabel": "Valeur", "xpack.stackConnectors.components.webhook.methodTextFieldLabel": "Méthode", - "xpack.stackConnectors.components.webhook.passphraseTextFieldLabel": "Phrase secrète", - "xpack.stackConnectors.components.webhook.passwordTextFieldLabel": "Mot de passe", - "xpack.stackConnectors.components.webhook.removeHeaderIconLabel": "Clé", "xpack.stackConnectors.components.webhook.selectMessageText": "Envoyer une requête à un service Web.", "xpack.stackConnectors.components.webhook.urlTextFieldLabel": "URL", - "xpack.stackConnectors.components.webhook.userTextFieldLabel": "Nom d'utilisateur", - "xpack.stackConnectors.components.webhook.verificationModeFieldLabel": "Mode de vérification", - "xpack.stackConnectors.components.webhook.viewCertificateAuthoritySwitch": "Ajouter une autorité de certificat", - "xpack.stackConnectors.components.webhook.viewHeadersSwitch": "Ajouter un en-tête HTTP", "xpack.stackConnectors.components.xmatters.authenticationLabel": "Authentification", "xpack.stackConnectors.components.xmatters.basicAuthButtonGroupLegend": "Authentification de base", "xpack.stackConnectors.components.xmatters.basicAuthLabel": "Authentification de base", @@ -39975,7 +39939,6 @@ "xpack.stackConnectors.webhook.authConfigurationError": "erreur lors de la configuration d'action webhook : authType doit être null ou undefined si hasAuth est faux", "xpack.stackConnectors.webhook.invalidResponseErrorMessage": "erreur lors de l'appel de webhook, réponse non valide", "xpack.stackConnectors.webhook.invalidResponseRetryLaterErrorMessage": "erreur lors de l'appel de webhook, réessayer ultérieurement", - "xpack.stackConnectors.webhook.invalidUsernamePassword": "doit préciser l'un des schémas suivants : utilisateur et mot de passe, crt et key (avec mot de passe facultatif) ou pfx (avec mot de passe facultatif)", "xpack.stackConnectors.webhook.requestFailedErrorMessage": "erreur lors de l'appel de webhook, requête échouée", "xpack.stackConnectors.webhook.title": "Webhook", "xpack.stackConnectors.webhook.unexpectedNullResponseErrorMessage": "réponse nulle inattendue de webhook", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e59e2a0379043..7e2f411d770c2 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -39284,7 +39284,6 @@ "xpack.stackConnectors.xmatters.invalidUrlError": "無効なsecretsUrl:{err}", "xpack.stackConnectors.xmatters.postingRetryErrorMessage": "xMattersフローのトリガーエラー:HTTPステータス{status}。しばらくたってから再試行してください", "xpack.stackConnectors.xmatters.unexpectedStatusErrorMessage": "xMattersフローのトリガーエラー:予期しないステータス{status}", - "xpack.stackConnectors.casesWebhook.invalidUsernamePassword": "ユーザーとパスワードの両方を指定する必要があります", "xpack.stackConnectors.casesWebhook.title": "Webフック - ケース管理", "xpack.stackConnectors.components.bedrock.accessKeySecret": "アクセスキー", "xpack.stackConnectors.components.bedrock.apiUrlTextFieldLabel": "URL", @@ -39299,9 +39298,7 @@ "xpack.stackConnectors.components.bedrock.selectMessageText": "Amazon Bedrockにリクエストを送信します。", "xpack.stackConnectors.components.bedrock.title": "Amazon Bedrock", "xpack.stackConnectors.components.bedrock.urlTextFieldLabel": "URL", - "xpack.stackConnectors.components.casesWebhook.addHeaderButton": "追加", "xpack.stackConnectors.components.casesWebhook.addVariable": "変数を追加", - "xpack.stackConnectors.components.casesWebhook.authenticationLabel": "認証", "xpack.stackConnectors.components.casesWebhook.caseCommentDesc": "Kibanaケースコメント", "xpack.stackConnectors.components.casesWebhook.caseDescriptionDesc": "Kibanaケース説明", "xpack.stackConnectors.components.casesWebhook.caseIdDesc": "KibanaケースID", @@ -39324,11 +39321,8 @@ "xpack.stackConnectors.components.casesWebhook.createIncidentResponseKeyTextFieldLabel": "ケース対応の作成の外部キー", "xpack.stackConnectors.components.casesWebhook.createIncidentUrlTextFieldLabel": "ケースURLを作成", "xpack.stackConnectors.components.casesWebhook.criticalLabel": "重大", - "xpack.stackConnectors.components.casesWebhook.deleteHeaderButton": "削除", "xpack.stackConnectors.components.casesWebhook.descriptionTextAreaFieldLabel": "説明", "xpack.stackConnectors.components.casesWebhook.docLink": "Webフックの構成 - ケース管理コネクター。", - "xpack.stackConnectors.components.casesWebhook.error.requiredAuthPasswordText": "パスワードが必要です。", - "xpack.stackConnectors.components.casesWebhook.error.requiredAuthUserNameText": "ユーザー名が必要です。", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentIncidentText": "コメントオブジェクトの作成は有効なJSONでなければなりません。", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentMethodText": "コメントメソッドを作成は必須です。", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentUrlText": "コメントURLの作成はURL形式でなければなりません。", @@ -39353,15 +39347,12 @@ "xpack.stackConnectors.components.casesWebhook.getIncidentUrlTextFieldLabel": "ケースURLを取得", "xpack.stackConnectors.components.casesWebhook.hasAuthSwitchLabel": "この Web フックの認証が必要です", "xpack.stackConnectors.components.casesWebhook.highLabel": "高", - "xpack.stackConnectors.components.casesWebhook.httpHeadersTitle": "使用中のヘッダー", "xpack.stackConnectors.components.casesWebhook.idFieldLabel": "ケースID", "xpack.stackConnectors.components.casesWebhook.jsonCodeEditorAriaLabel": "コードエディター", "xpack.stackConnectors.components.casesWebhook.jsonFieldLabel": "JSON", - "xpack.stackConnectors.components.casesWebhook.keyTextFieldLabel": "キー", "xpack.stackConnectors.components.casesWebhook.lowLabel": "低", "xpack.stackConnectors.components.casesWebhook.mediumLabel": "中", "xpack.stackConnectors.components.casesWebhook.next": "次へ", - "xpack.stackConnectors.components.casesWebhook.passwordTextFieldLabel": "パスワード", "xpack.stackConnectors.components.casesWebhook.previous": "前へ", "xpack.stackConnectors.components.casesWebhook.selectMessageText": "ケース管理Webサービスにリクエストを送信します。", "xpack.stackConnectors.components.casesWebhook.severityFieldLabel": "深刻度", @@ -39386,9 +39377,6 @@ "xpack.stackConnectors.components.casesWebhook.updateIncidentMethodTextFieldLabel": "ケースメソッドを更新", "xpack.stackConnectors.components.casesWebhook.updateIncidentUrlHelp": "ケースを更新するAPI URL。", "xpack.stackConnectors.components.casesWebhook.updateIncidentUrlTextFieldLabel": "ケースURLを更新", - "xpack.stackConnectors.components.casesWebhook.userTextFieldLabel": "ユーザー名", - "xpack.stackConnectors.components.casesWebhook.valueTextFieldLabel": "値", - "xpack.stackConnectors.components.casesWebhook.viewHeadersSwitch": "HTTP ヘッダーを追加", "xpack.stackConnectors.components.casesWebhook.viewIncidentUrlHelp": "外部システムでケースを表示するURL。変数セレクターを使用して、外部システムIDまたは外部システムタイトルをURLに追加します。", "xpack.stackConnectors.components.casesWebhook.viewIncidentUrlTextFieldLabel": "外部ケース表示URL", "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webフック - ケース管理データ", @@ -39738,39 +39726,15 @@ "xpack.stackConnectors.components.teams.messageTextAreaFieldLabel": "メッセージ", "xpack.stackConnectors.components.teams.selectMessageText": "メッセージを Microsoft Teams チャネルに送信します。", "xpack.stackConnectors.components.teams.webhookUrlHelpLabel": "Microsoft Teams Web フック URL を作成", - "xpack.stackConnectors.components.webhook.addHeaderButtonLabel": "ヘッダーを追加", - "xpack.stackConnectors.components.webhook.authenticationLabel": "認証", - "xpack.stackConnectors.components.webhook.authenticationMethodBasicLabel": "基本認証", - "xpack.stackConnectors.components.webhook.authenticationMethodNoneLabel": "なし", - "xpack.stackConnectors.components.webhook.authenticationMethodSSLLabel": "SSL認証", "xpack.stackConnectors.components.webhook.bodyCodeEditorAriaLabel": "コードエディター", "xpack.stackConnectors.components.webhook.bodyFieldLabel": "本文", - "xpack.stackConnectors.components.webhook.certTypeCrtKeyLabel": "CRTおよびKEYファイル", - "xpack.stackConnectors.components.webhook.certTypePfxLabel": "PFXファイル", "xpack.stackConnectors.components.webhook.connectorTypeTitle": "Web フックデータ", - "xpack.stackConnectors.components.webhook.editCACallout": "このWebフックには既存の認証局ファイルがあります。新しいファイルをアップロードして置き換えてください。", "xpack.stackConnectors.components.webhook.error.invalidUrlTextField": "URL が無効です。", - "xpack.stackConnectors.components.webhook.error.requiredAuthUserNameText": "ユーザー名が必要です。", "xpack.stackConnectors.components.webhook.error.requiredMethodText": "メソッドが必要です。", "xpack.stackConnectors.components.webhook.error.requiredWebhookBodyText": "本文が必要です。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookCAText": "CAファイルが必要です。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookCRTText": "CRTファイルが必要です。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookKEYText": "KEYファイルが必要です。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookPasswordText": "パスワードが必要です。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookPFXText": "PFXファイルが必要です。", - "xpack.stackConnectors.components.webhook.hasAuthSwitchLabel": "この Web フックの認証が必要です", - "xpack.stackConnectors.components.webhook.headerKeyTextFieldLabel": "キー", - "xpack.stackConnectors.components.webhook.headerValueTextFieldLabel": "値", "xpack.stackConnectors.components.webhook.methodTextFieldLabel": "メソド", - "xpack.stackConnectors.components.webhook.passphraseTextFieldLabel": "パスフレーズ", - "xpack.stackConnectors.components.webhook.passwordTextFieldLabel": "パスワード", - "xpack.stackConnectors.components.webhook.removeHeaderIconLabel": "キー", "xpack.stackConnectors.components.webhook.selectMessageText": "Web サービスにリクエストを送信してください。", "xpack.stackConnectors.components.webhook.urlTextFieldLabel": "URL", - "xpack.stackConnectors.components.webhook.userTextFieldLabel": "ユーザー名", - "xpack.stackConnectors.components.webhook.verificationModeFieldLabel": "認証モード", - "xpack.stackConnectors.components.webhook.viewCertificateAuthoritySwitch": "認証局を追加", - "xpack.stackConnectors.components.webhook.viewHeadersSwitch": "HTTP ヘッダーを追加", "xpack.stackConnectors.components.xmatters.authenticationLabel": "認証", "xpack.stackConnectors.components.xmatters.basicAuthButtonGroupLegend": "基本認証", "xpack.stackConnectors.components.xmatters.basicAuthLabel": "基本認証", @@ -39947,7 +39911,6 @@ "xpack.stackConnectors.webhook.authConfigurationError": "webフックアクションの構成エラー:hasAuthがfalseの場合、authTypeはnullまたはundefinedでなければなりません", "xpack.stackConnectors.webhook.invalidResponseErrorMessage": "Webフックの呼び出しエラー、無効な応答", "xpack.stackConnectors.webhook.invalidResponseRetryLaterErrorMessage": "Webフックの呼び出しエラー、後ほど再試行", - "xpack.stackConnectors.webhook.invalidUsernamePassword": "ユーザーとパスワード、crtと鍵(任意のパスワード付き)、またはpfx(任意のパスワード付き)のいずれかのスキーマを指定する必要があります", "xpack.stackConnectors.webhook.requestFailedErrorMessage": "Webフックの呼び出しエラー。要求が失敗しました", "xpack.stackConnectors.webhook.title": "Web フック", "xpack.stackConnectors.webhook.unexpectedNullResponseErrorMessage": "Webフックからの予期しないnull応答", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 80a079b82c701..d43efdcf980fb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -39330,7 +39330,6 @@ "xpack.stackConnectors.xmatters.invalidUrlError": "secretsUrl 无效:{err}", "xpack.stackConnectors.xmatters.postingRetryErrorMessage": "触发 xMatters 流时出错:http 状态为 {status},请稍后重试", "xpack.stackConnectors.xmatters.unexpectedStatusErrorMessage": "触发 xMatters 流时出错:非预期状态 {status}", - "xpack.stackConnectors.casesWebhook.invalidUsernamePassword": "必须指定用户及密码", "xpack.stackConnectors.casesWebhook.title": "Webhook - 案例管理", "xpack.stackConnectors.components.bedrock.accessKeySecret": "访问密钥", "xpack.stackConnectors.components.bedrock.apiUrlTextFieldLabel": "URL", @@ -39345,9 +39344,7 @@ "xpack.stackConnectors.components.bedrock.selectMessageText": "向 Amazon Bedrock 发送请求。", "xpack.stackConnectors.components.bedrock.title": "Amazon Bedrock", "xpack.stackConnectors.components.bedrock.urlTextFieldLabel": "URL", - "xpack.stackConnectors.components.casesWebhook.addHeaderButton": "添加", "xpack.stackConnectors.components.casesWebhook.addVariable": "添加变量", - "xpack.stackConnectors.components.casesWebhook.authenticationLabel": "身份验证", "xpack.stackConnectors.components.casesWebhook.caseCommentDesc": "Kibana 案例注释", "xpack.stackConnectors.components.casesWebhook.caseDescriptionDesc": "Kibana 案例描述", "xpack.stackConnectors.components.casesWebhook.caseIdDesc": "Kibana 案例 ID", @@ -39370,11 +39367,8 @@ "xpack.stackConnectors.components.casesWebhook.createIncidentResponseKeyTextFieldLabel": "创建案例响应外部键", "xpack.stackConnectors.components.casesWebhook.createIncidentUrlTextFieldLabel": "创建案例 URL", "xpack.stackConnectors.components.casesWebhook.criticalLabel": "紧急", - "xpack.stackConnectors.components.casesWebhook.deleteHeaderButton": "删除", "xpack.stackConnectors.components.casesWebhook.descriptionTextAreaFieldLabel": "描述", "xpack.stackConnectors.components.casesWebhook.docLink": "正在配置 Webhook - 案例管理连接器。", - "xpack.stackConnectors.components.casesWebhook.error.requiredAuthPasswordText": "“密码”必填。", - "xpack.stackConnectors.components.casesWebhook.error.requiredAuthUserNameText": "“用户名”必填。", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentIncidentText": "创建注释对象必须为有效 JSON。", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentMethodText": "“创建注释方法”必填。", "xpack.stackConnectors.components.casesWebhook.error.requiredCreateCommentUrlText": "创建注释 URL 必须为 URL 格式。", @@ -39399,15 +39393,12 @@ "xpack.stackConnectors.components.casesWebhook.getIncidentUrlTextFieldLabel": "获取案例 URL", "xpack.stackConnectors.components.casesWebhook.hasAuthSwitchLabel": "此 Webhook 需要身份验证", "xpack.stackConnectors.components.casesWebhook.highLabel": "高", - "xpack.stackConnectors.components.casesWebhook.httpHeadersTitle": "在用的标头", "xpack.stackConnectors.components.casesWebhook.idFieldLabel": "案例 ID", "xpack.stackConnectors.components.casesWebhook.jsonCodeEditorAriaLabel": "代码编辑器", "xpack.stackConnectors.components.casesWebhook.jsonFieldLabel": "JSON", - "xpack.stackConnectors.components.casesWebhook.keyTextFieldLabel": "钥匙", "xpack.stackConnectors.components.casesWebhook.lowLabel": "低", "xpack.stackConnectors.components.casesWebhook.mediumLabel": "中", "xpack.stackConnectors.components.casesWebhook.next": "下一步", - "xpack.stackConnectors.components.casesWebhook.passwordTextFieldLabel": "密码", "xpack.stackConnectors.components.casesWebhook.previous": "上一步", "xpack.stackConnectors.components.casesWebhook.selectMessageText": "发送请求到案例管理 Web 服务。", "xpack.stackConnectors.components.casesWebhook.severityFieldLabel": "严重性", @@ -39432,9 +39423,6 @@ "xpack.stackConnectors.components.casesWebhook.updateIncidentMethodTextFieldLabel": "更新案例方法", "xpack.stackConnectors.components.casesWebhook.updateIncidentUrlHelp": "用于更新案例的 API URL。", "xpack.stackConnectors.components.casesWebhook.updateIncidentUrlTextFieldLabel": "更新案例 URL", - "xpack.stackConnectors.components.casesWebhook.userTextFieldLabel": "用户名", - "xpack.stackConnectors.components.casesWebhook.valueTextFieldLabel": "值", - "xpack.stackConnectors.components.casesWebhook.viewHeadersSwitch": "添加 HTTP 标头", "xpack.stackConnectors.components.casesWebhook.viewIncidentUrlHelp": "用于查看外部系统中的案例的 URL。使用变量选择器添加外部系统 ID 或外部系统标题到 URL。", "xpack.stackConnectors.components.casesWebhook.viewIncidentUrlTextFieldLabel": "外部案例查看 URL", "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - 案例管理数据", @@ -39784,39 +39772,15 @@ "xpack.stackConnectors.components.teams.messageTextAreaFieldLabel": "消息", "xpack.stackConnectors.components.teams.selectMessageText": "向 Microsoft Teams 频道发送消息。", "xpack.stackConnectors.components.teams.webhookUrlHelpLabel": "创建 Microsoft Teams Webhook URL", - "xpack.stackConnectors.components.webhook.addHeaderButtonLabel": "添加标头", - "xpack.stackConnectors.components.webhook.authenticationLabel": "身份验证", - "xpack.stackConnectors.components.webhook.authenticationMethodBasicLabel": "基本身份验证", - "xpack.stackConnectors.components.webhook.authenticationMethodNoneLabel": "无", - "xpack.stackConnectors.components.webhook.authenticationMethodSSLLabel": "SSL 身份验证", "xpack.stackConnectors.components.webhook.bodyCodeEditorAriaLabel": "代码编辑器", "xpack.stackConnectors.components.webhook.bodyFieldLabel": "正文", - "xpack.stackConnectors.components.webhook.certTypeCrtKeyLabel": "CRT 和 KEY 文件", - "xpack.stackConnectors.components.webhook.certTypePfxLabel": "PFX 文件", "xpack.stackConnectors.components.webhook.connectorTypeTitle": "Webhook 数据", - "xpack.stackConnectors.components.webhook.editCACallout": "此 Webhook 具有现有证书颁发机构文件。上传新文件将其替换。", "xpack.stackConnectors.components.webhook.error.invalidUrlTextField": "URL 无效。", - "xpack.stackConnectors.components.webhook.error.requiredAuthUserNameText": "“用户名”必填。", "xpack.stackConnectors.components.webhook.error.requiredMethodText": "“方法”必填", "xpack.stackConnectors.components.webhook.error.requiredWebhookBodyText": "“正文”必填。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookCAText": "CA 文件必填。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookCRTText": "CRT 文件必填。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookKEYText": "KEY 文件必填。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookPasswordText": "“密码”必填。", - "xpack.stackConnectors.components.webhook.error.requiredWebhookPFXText": "PFX 文件必填。", - "xpack.stackConnectors.components.webhook.hasAuthSwitchLabel": "此 Webhook 需要身份验证", - "xpack.stackConnectors.components.webhook.headerKeyTextFieldLabel": "钥匙", - "xpack.stackConnectors.components.webhook.headerValueTextFieldLabel": "值", "xpack.stackConnectors.components.webhook.methodTextFieldLabel": "方法", - "xpack.stackConnectors.components.webhook.passphraseTextFieldLabel": "密码", - "xpack.stackConnectors.components.webhook.passwordTextFieldLabel": "密码", - "xpack.stackConnectors.components.webhook.removeHeaderIconLabel": "钥匙", "xpack.stackConnectors.components.webhook.selectMessageText": "将请求发送到 Web 服务。", "xpack.stackConnectors.components.webhook.urlTextFieldLabel": "URL", - "xpack.stackConnectors.components.webhook.userTextFieldLabel": "用户名", - "xpack.stackConnectors.components.webhook.verificationModeFieldLabel": "验证模式", - "xpack.stackConnectors.components.webhook.viewCertificateAuthoritySwitch": "添加证书颁发机构", - "xpack.stackConnectors.components.webhook.viewHeadersSwitch": "添加 HTTP 标头", "xpack.stackConnectors.components.xmatters.authenticationLabel": "身份验证", "xpack.stackConnectors.components.xmatters.basicAuthButtonGroupLegend": "基本身份验证", "xpack.stackConnectors.components.xmatters.basicAuthLabel": "基本身份验证", @@ -39993,7 +39957,6 @@ "xpack.stackConnectors.webhook.authConfigurationError": "配置 Webhook 操作时出错:如果 hasAuth 为 false,authType 必须为 null 或未定义", "xpack.stackConnectors.webhook.invalidResponseErrorMessage": "调用 webhook 时出错,响应无效", "xpack.stackConnectors.webhook.invalidResponseRetryLaterErrorMessage": "调用 webhook 时出错,请稍后重试", - "xpack.stackConnectors.webhook.invalidUsernamePassword": "必须指定以下方案之一:用户和密码;crt 和密钥(密码可选);或 pfx(密码可选)", "xpack.stackConnectors.webhook.requestFailedErrorMessage": "调用 webhook 时出错,请求失败", "xpack.stackConnectors.webhook.title": "Webhook", "xpack.stackConnectors.webhook.unexpectedNullResponseErrorMessage": "来自 Webhook 的异常空响应", diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts index 35401f0c426a2..f26ba86f6fa3a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts @@ -202,7 +202,7 @@ export default function casesWebhookTest({ getService }: FtrProviderContext) { statusCode: 400, error: 'Bad Request', message: - 'error validating action type connector: both user and password must be specified', + 'error validating action type connector: must specify a secrets configuration', }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts index 22ac52dc2a333..091707df88d0a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts @@ -18,7 +18,7 @@ import { import { getCreateExceptionListDetectionSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock'; import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock'; -import { WebhookAuthType } from '@kbn/stack-connectors-plugin/common/webhook/constants'; +import { AuthType } from '@kbn/stack-connectors-plugin/common/auth/constants'; import { BaseDefaultableFields } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { binaryToString, @@ -190,7 +190,7 @@ export default ({ getService }: FtrProviderContext): void => { attributes: { actionTypeId: '.webhook', config: { - authType: WebhookAuthType.Basic, + authType: AuthType.Basic, hasAuth: true, method: 'post', url: 'http://localhost', From 4a95ffbd9398a715504f55d54c0d6a8a19d52f7e Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 18 Jun 2024 11:03:21 +0100 Subject: [PATCH 040/127] [Entity Analytics] Create public versions of asset criticality get,upsert,delete and csv upload APIs (#186169) ## Summary Adds 4 new public APIs for managing asset criticality. These are public versions of our existing internal asset criticality APIs: - Get record `GET /api/asset_criticality?id_field=x?id_value=y` - Upsert record`POST /api/asset_criticality` - Delete record `DELETE /api/asset_criticality?id_field=x?id_value=y` - Bulk CSV Upload `POST /api/asset_criticality/upload_csv` We will delete the internal versions in the future but for now we keep both. I have switched the tests and UI to use the public APIs. I have also moved our API versions to constants. ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../create_asset_criticality.schema.yaml | 20 ++ .../delete_asset_criticality.schema.yaml | 13 ++ .../get_asset_criticality.schema.yaml | 19 ++ .../upload_asset_criticality_csv.schema.yaml | 26 +++ .../asset_criticality/constants.ts | 15 +- .../common/entity_analytics/constants.ts | 9 + .../public/entity_analytics/api/api.ts | 40 ++-- .../asset_criticality/routes/delete.ts | 122 ++++++---- .../asset_criticality/routes/get.ts | 122 ++++++---- .../asset_criticality/routes/privileges.ts | 9 +- .../register_asset_criticality_routes.ts | 34 ++- .../asset_criticality/routes/status.ts | 72 +++--- .../asset_criticality/routes/upload_csv.ts | 221 +++++++++++------- .../asset_criticality/routes/upsert.ts | 134 +++++++---- .../utils/asset_criticality.ts | 33 +-- 15 files changed, 585 insertions(+), 304 deletions(-) diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml index 64f321c5a56cb..4b5e52b5eb211 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml @@ -15,6 +15,26 @@ paths: x-labels: [ess, serverless] x-internal: true operationId: AssetCriticalityCreateRecord + summary: Deprecated Internal Create Criticality Record + requestBody: + required: true + content: + application/json: + schema: + $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: './common.schema.yaml#/components/schemas/AssetCriticalityRecord' + '400': + description: Invalid request + /api/asset_criticality: + post: + x-labels: [ess, serverless] + operationId: AssetCriticalityCreateRecord summary: Create Criticality Record requestBody: required: true diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml index be882228c0bb0..94e1cc82e15ad 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml @@ -15,6 +15,19 @@ paths: x-labels: [ess, serverless] x-internal: true operationId: AssetCriticalityDeleteRecord + summary: Deprecated Internal Delete Criticality Record + parameters: + - $ref: './common.schema.yaml#/components/parameters/id_value' + - $ref: './common.schema.yaml#/components/parameters/id_field' + responses: + '200': + description: Successful response + '400': + description: Invalid request + /api/asset_criticality: + delete: + x-labels: [ess, serverless] + operationId: AssetCriticalityDeleteRecord summary: Delete Criticality Record parameters: - $ref: './common.schema.yaml#/components/parameters/id_value' diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml index 664d8dbace2bf..56f3e37de1126 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml @@ -15,6 +15,25 @@ paths: x-labels: [ess, serverless] x-internal: true operationId: AssetCriticalityGetRecord + summary: Deprecated Internal Get Criticality Record + parameters: + - $ref: './common.schema.yaml#/components/parameters/id_value' + - $ref: './common.schema.yaml#/components/parameters/id_field' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: './common.schema.yaml#/components/schemas/AssetCriticalityRecord' + '400': + description: Invalid request + '404': + description: Criticality record not found + /api/asset_criticality: + get: + x-labels: [ess, serverless] + operationId: AssetCriticalityGetRecord summary: Get Criticality Record parameters: - $ref: './common.schema.yaml#/components/parameters/id_value' diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml index 440955f8954c2..933839cea43a3 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml @@ -11,6 +11,32 @@ servers: default: '5601' paths: /internal/asset_criticality/upload_csv: + post: + x-labels: [ess, serverless] + x-internal: true + summary: Deprecated internal API which Uploads a CSV file containing asset criticality data + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + description: The CSV file to upload. + required: + - file + responses: + '200': + description: CSV upload successful + content: + application/json: + schema: + $ref: '#/components/schemas/AssetCriticalityCsvUploadResponse' + '413': + description: File too large + /api/asset_criticality/upload_csv: post: x-labels: [ess, serverless] x-internal: true diff --git a/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts b/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts index 73d9cccabc940..d7d9854834d09 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts @@ -5,10 +5,17 @@ * 2.0. */ -export const ASSET_CRITICALITY_URL = `/internal/asset_criticality` as const; -export const ASSET_CRITICALITY_PRIVILEGES_URL = `${ASSET_CRITICALITY_URL}/privileges` as const; -export const ASSET_CRITICALITY_STATUS_URL = `${ASSET_CRITICALITY_URL}/status` as const; -export const ASSET_CRITICALITY_CSV_UPLOAD_URL = `${ASSET_CRITICALITY_URL}/upload_csv` as const; +export const ASSET_CRITICALITY_INTERNAL_URL = `/internal/asset_criticality` as const; +export const ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL = + `${ASSET_CRITICALITY_INTERNAL_URL}/privileges` as const; +export const ASSET_CRITICALITY_INTERNAL_STATUS_URL = + `${ASSET_CRITICALITY_INTERNAL_URL}/status` as const; +export const ASSET_CRITICALITY_INTERNAL_CSV_UPLOAD_URL = + `${ASSET_CRITICALITY_INTERNAL_URL}/upload_csv` as const; + +export const ASSET_CRITICALITY_PUBLIC_URL = `/api/asset_criticality` as const; +export const ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL = + `${ASSET_CRITICALITY_PUBLIC_URL}/upload_csv` as const; export const ASSET_CRITICALITY_INDEX_PATTERN = '.asset-criticality.asset-criticality-*'; diff --git a/x-pack/plugins/security_solution/common/entity_analytics/constants.ts b/x-pack/plugins/security_solution/common/entity_analytics/constants.ts index 08ee2d6afd517..c0a9567acd09c 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/constants.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/constants.ts @@ -8,3 +8,12 @@ export * from './asset_criticality/constants'; export * from './risk_engine/constants'; export * from './risk_score/constants'; + +export const API_VERSIONS = { + public: { + v1: '2023-10-31', + }, + internal: { + v1: '1', + }, +}; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts index 9903f6eb2ef78..da391a9b30432 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts @@ -31,12 +31,13 @@ import { RISK_ENGINE_DISABLE_URL, RISK_ENGINE_INIT_URL, RISK_ENGINE_PRIVILEGES_URL, - ASSET_CRITICALITY_PRIVILEGES_URL, - ASSET_CRITICALITY_URL, + ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL, + ASSET_CRITICALITY_PUBLIC_URL, RISK_SCORE_INDEX_STATUS_API_URL, RISK_ENGINE_SETTINGS_URL, - ASSET_CRITICALITY_CSV_UPLOAD_URL, + ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, RISK_SCORE_ENTITY_CALCULATION_URL, + API_VERSIONS, } from '../../../common/constants'; import type { RiskEngineSettingsResponse } from '../../../common/api/entity_analytics/risk_engine'; import type { SnakeToCamelCase } from '../common/utils'; @@ -127,7 +128,7 @@ export const useEntityAnalyticsRoutes = () => { * Get asset criticality privileges */ const fetchAssetCriticalityPrivileges = () => - http.fetch(ASSET_CRITICALITY_PRIVILEGES_URL, { + http.fetch(ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL, { version: '1', method: 'GET', }); @@ -140,8 +141,8 @@ export const useEntityAnalyticsRoutes = () => { refresh?: 'wait_for'; } ): Promise => - http.fetch(ASSET_CRITICALITY_URL, { - version: '1', + http.fetch(ASSET_CRITICALITY_PUBLIC_URL, { + version: API_VERSIONS.public.v1, method: 'POST', body: JSON.stringify({ id_value: params.idValue, @@ -154,8 +155,8 @@ export const useEntityAnalyticsRoutes = () => { const deleteAssetCriticality = async ( params: Pick & { refresh?: 'wait_for' } ): Promise<{ deleted: true }> => { - await http.fetch(ASSET_CRITICALITY_URL, { - version: '1', + await http.fetch(ASSET_CRITICALITY_PUBLIC_URL, { + version: API_VERSIONS.public.v1, method: 'DELETE', query: { id_value: params.idValue, id_field: params.idField, refresh: params.refresh }, }); @@ -170,8 +171,8 @@ export const useEntityAnalyticsRoutes = () => { const fetchAssetCriticality = async ( params: Pick ): Promise => { - return http.fetch(ASSET_CRITICALITY_URL, { - version: '1', + return http.fetch(ASSET_CRITICALITY_PUBLIC_URL, { + version: API_VERSIONS.public.v1, method: 'GET', query: { id_value: params.idValue, id_field: params.idField }, }); @@ -185,14 +186,17 @@ export const useEntityAnalyticsRoutes = () => { const body = new FormData(); body.append('file', file); - return http.fetch(ASSET_CRITICALITY_CSV_UPLOAD_URL, { - version: '1', - method: 'POST', - headers: { - 'Content-Type': undefined, // Lets the browser set the appropriate content type - }, - body, - }); + return http.fetch( + ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, + { + version: API_VERSIONS.public.v1, + method: 'POST', + headers: { + 'Content-Type': undefined, // Lets the browser set the appropriate content type + }, + body, + } + ); }; const getRiskScoreIndexStatus = ({ diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts index 6f1d677d414c5..e2737c6ebe045 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts @@ -4,13 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { Logger } from '@kbn/core/server'; +import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import type { SecuritySolutionRequestHandlerContext } from '../../../../types'; import { - ASSET_CRITICALITY_URL, + ASSET_CRITICALITY_PUBLIC_URL, + ASSET_CRITICALITY_INTERNAL_URL, APP_ID, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '../../../../../common/constants'; import { DeleteAssetCriticalityRecord } from '../../../../../common/api/entity_analytics/asset_criticality'; import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; @@ -19,64 +22,101 @@ import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setti import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; -export const assetCriticalityDeleteRoute = ( + +type DeleteHandler = ( + context: SecuritySolutionRequestHandlerContext, + request: { + query: DeleteAssetCriticalityRecord; + }, + response: KibanaResponseFactory +) => Promise; + +const handler: (logger: Logger) => DeleteHandler = + (logger) => async (context, request, response) => { + const securitySolution = await context.securitySolution; + + securitySolution.getAuditLogger()?.log({ + message: 'User attempted to un-assign asset criticality from an entity', + event: { + action: AssetCriticalityAuditActions.ASSET_CRITICALITY_UNASSIGN, + category: AUDIT_CATEGORY.DATABASE, + type: AUDIT_TYPE.DELETION, + outcome: AUDIT_OUTCOME.UNKNOWN, + }, + }); + + const siemResponse = buildSiemResponse(response); + try { + await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); + await checkAndInitAssetCriticalityResources(context, logger); + + const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); + await assetCriticalityClient.delete( + { + idField: request.query.id_field, + idValue: request.query.id_value, + }, + request.query.refresh + ); + + return response.ok(); + } catch (e) { + const error = transformError(e); + + return siemResponse.error({ + statusCode: error.statusCode, + body: { message: error.message, full_error: JSON.stringify(e) }, + bypassErrorFormat: true, + }); + } + }; + +export const assetCriticalityInternalDeleteRoute = ( router: EntityAnalyticsRoutesDeps['router'], logger: Logger ) => { router.versioned .delete({ access: 'internal', - path: ASSET_CRITICALITY_URL, + path: ASSET_CRITICALITY_INTERNAL_URL, options: { tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], }, }) .addVersion( { - version: '1', + version: API_VERSIONS.internal.v1, validate: { request: { query: buildRouteValidationWithZod(DeleteAssetCriticalityRecord), }, }, }, - async (context, request, response) => { - const securitySolution = await context.securitySolution; + handler(logger) + ); +}; - securitySolution.getAuditLogger()?.log({ - message: 'User attempted to un-assign asset criticality from an entity', - event: { - action: AssetCriticalityAuditActions.ASSET_CRITICALITY_UNASSIGN, - category: AUDIT_CATEGORY.DATABASE, - type: AUDIT_TYPE.DELETION, - outcome: AUDIT_OUTCOME.UNKNOWN, +export const assetCriticalityPublicDeleteRoute = ( + router: EntityAnalyticsRoutesDeps['router'], + logger: Logger +) => { + router.versioned + .delete({ + access: 'public', + path: ASSET_CRITICALITY_PUBLIC_URL, + options: { + tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + validate: { + request: { + query: buildRouteValidationWithZod(DeleteAssetCriticalityRecord), }, - }); - - const siemResponse = buildSiemResponse(response); - try { - await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); - await checkAndInitAssetCriticalityResources(context, logger); - - const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); - await assetCriticalityClient.delete( - { - idField: request.query.id_field, - idValue: request.query.id_value, - }, - request.query.refresh - ); - - return response.ok(); - } catch (e) { - const error = transformError(e); - - return siemResponse.error({ - statusCode: error.statusCode, - body: { message: error.message, full_error: JSON.stringify(e) }, - bypassErrorFormat: true, - }); - } - } + }, + }, + handler(logger) ); }; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts index fd2a826df117a..57e52724b94ce 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts @@ -4,13 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { Logger } from '@kbn/core/server'; +import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import type { SecuritySolutionRequestHandlerContext } from '../../../../types'; import { - ASSET_CRITICALITY_URL, + ASSET_CRITICALITY_INTERNAL_URL, + ASSET_CRITICALITY_PUBLIC_URL, APP_ID, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; @@ -19,64 +22,99 @@ import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setti import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; -export const assetCriticalityGetRoute = ( +type GetHandler = ( + context: SecuritySolutionRequestHandlerContext, + request: { + query: AssetCriticalityRecordIdParts; + }, + response: KibanaResponseFactory +) => Promise; + +const handler: (logger: Logger) => GetHandler = (logger) => async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + try { + await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); + await checkAndInitAssetCriticalityResources(context, logger); + + const securitySolution = await context.securitySolution; + const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); + const record = await assetCriticalityClient.get({ + idField: request.query.id_field, + idValue: request.query.id_value, + }); + + if (!record) { + return response.notFound(); + } + + securitySolution.getAuditLogger()?.log({ + message: 'User accessed the criticality level for an entity', + event: { + action: AssetCriticalityAuditActions.ASSET_CRITICALITY_GET, + category: AUDIT_CATEGORY.DATABASE, + type: AUDIT_TYPE.ACCESS, + outcome: AUDIT_OUTCOME.SUCCESS, + }, + }); + + return response.ok({ body: record }); + } catch (e) { + const error = transformError(e); + + return siemResponse.error({ + statusCode: error.statusCode, + body: { message: error.message, full_error: JSON.stringify(e) }, + bypassErrorFormat: true, + }); + } +}; + +export const assetCriticalityInternalGetRoute = ( router: EntityAnalyticsRoutesDeps['router'], logger: Logger ) => { router.versioned .get({ access: 'internal', - path: ASSET_CRITICALITY_URL, + path: ASSET_CRITICALITY_INTERNAL_URL, options: { tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], }, }) .addVersion( { - version: '1', + version: API_VERSIONS.internal.v1, validate: { request: { query: buildRouteValidationWithZod(AssetCriticalityRecordIdParts), }, }, }, - async (context, request, response) => { - const siemResponse = buildSiemResponse(response); - try { - await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); - await checkAndInitAssetCriticalityResources(context, logger); - - const securitySolution = await context.securitySolution; - const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); - const record = await assetCriticalityClient.get({ - idField: request.query.id_field, - idValue: request.query.id_value, - }); - - if (!record) { - return response.notFound(); - } - - securitySolution.getAuditLogger()?.log({ - message: 'User accessed the criticality level for an entity', - event: { - action: AssetCriticalityAuditActions.ASSET_CRITICALITY_GET, - category: AUDIT_CATEGORY.DATABASE, - type: AUDIT_TYPE.ACCESS, - outcome: AUDIT_OUTCOME.SUCCESS, - }, - }); - - return response.ok({ body: record }); - } catch (e) { - const error = transformError(e); + handler(logger) + ); +}; - return siemResponse.error({ - statusCode: error.statusCode, - body: { message: error.message, full_error: JSON.stringify(e) }, - bypassErrorFormat: true, - }); - } - } +export const assetCriticalityPublicGetRoute = ( + router: EntityAnalyticsRoutesDeps['router'], + logger: Logger +) => { + router.versioned + .get({ + access: 'public', + path: ASSET_CRITICALITY_PUBLIC_URL, + options: { + tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + validate: { + request: { + query: buildRouteValidationWithZod(AssetCriticalityRecordIdParts), + }, + }, + }, + handler(logger) ); }; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/privileges.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/privileges.ts index a339ee994c8c2..a3b4c48d828df 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/privileges.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/privileges.ts @@ -8,9 +8,10 @@ import type { Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { - ASSET_CRITICALITY_PRIVILEGES_URL, + ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL, APP_ID, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; import { getUserAssetCriticalityPrivileges } from '../get_user_asset_criticality_privileges'; @@ -19,7 +20,7 @@ import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; -export const assetCriticalityPrivilegesRoute = ( +export const assetCriticalityInternalPrivilegesRoute = ( router: EntityAnalyticsRoutesDeps['router'], logger: Logger, getStartServices: EntityAnalyticsRoutesDeps['getStartServices'] @@ -27,14 +28,14 @@ export const assetCriticalityPrivilegesRoute = ( router.versioned .get({ access: 'internal', - path: ASSET_CRITICALITY_PRIVILEGES_URL, + path: ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL, options: { tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], }, }) .addVersion( { - version: '1', + version: API_VERSIONS.internal.v1, validate: false, }, async (context, request, response) => { diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts index 518602a4bc9b7..c211b1260b664 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts @@ -4,12 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { assetCriticalityStatusRoute } from './status'; -import { assetCriticalityUpsertRoute } from './upsert'; -import { assetCriticalityGetRoute } from './get'; -import { assetCriticalityDeleteRoute } from './delete'; -import { assetCriticalityPrivilegesRoute } from './privileges'; -import { assetCriticalityCSVUploadRoute } from './upload_csv'; +import { assetCriticalityInternalStatusRoute } from './status'; +import { assetCriticalityPublicUpsertRoute, assetCriticalityInternalUpsertRoute } from './upsert'; +import { assetCriticalityInternalGetRoute, assetCriticalityPublicGetRoute } from './get'; +import { assetCriticalityPublicDeleteRoute, assetCriticalityInternalDeleteRoute } from './delete'; +import { assetCriticalityInternalPrivilegesRoute } from './privileges'; +import { + assetCriticalityInternalCSVUploadRoute, + assetCriticalityPublicCSVUploadRoute, +} from './upload_csv'; import type { EntityAnalyticsRoutesDeps } from '../../types'; export const registerAssetCriticalityRoutes = ({ @@ -18,10 +21,17 @@ export const registerAssetCriticalityRoutes = ({ config, getStartServices, }: EntityAnalyticsRoutesDeps) => { - assetCriticalityStatusRoute(router, logger); - assetCriticalityUpsertRoute(router, logger); - assetCriticalityGetRoute(router, logger); - assetCriticalityDeleteRoute(router, logger); - assetCriticalityPrivilegesRoute(router, logger, getStartServices); - assetCriticalityCSVUploadRoute(router, logger, config, getStartServices); + // Internal routes + assetCriticalityInternalCSVUploadRoute(router, logger, config, getStartServices); + assetCriticalityInternalDeleteRoute(router, logger); + assetCriticalityInternalGetRoute(router, logger); + assetCriticalityInternalPrivilegesRoute(router, logger, getStartServices); + assetCriticalityInternalStatusRoute(router, logger); + assetCriticalityInternalUpsertRoute(router, logger); + + // Public routes + assetCriticalityPublicCSVUploadRoute(router, logger, config, getStartServices); + assetCriticalityPublicDeleteRoute(router, logger); + assetCriticalityPublicGetRoute(router, logger); + assetCriticalityPublicUpsertRoute(router, logger); }; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts index 27910cfd40631..2afa73ed5a059 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts @@ -9,9 +9,10 @@ import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { AssetCriticalityStatusResponse } from '../../../../../common/api/entity_analytics/asset_criticality'; import { - ASSET_CRITICALITY_STATUS_URL, + ASSET_CRITICALITY_INTERNAL_STATUS_URL, APP_ID, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '../../../../../common/constants'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; import type { EntityAnalyticsRoutesDeps } from '../../types'; @@ -19,53 +20,56 @@ import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setti import { AssetCriticalityAuditActions } from '../audit'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; -export const assetCriticalityStatusRoute = ( +export const assetCriticalityInternalStatusRoute = ( router: EntityAnalyticsRoutesDeps['router'], logger: Logger ) => { router.versioned .get({ access: 'internal', - path: ASSET_CRITICALITY_STATUS_URL, + path: ASSET_CRITICALITY_INTERNAL_STATUS_URL, options: { tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], }, }) - .addVersion({ version: '1', validate: {} }, async (context, request, response) => { - const siemResponse = buildSiemResponse(response); - try { - await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); - await checkAndInitAssetCriticalityResources(context, logger); + .addVersion( + { version: API_VERSIONS.internal.v1, validate: {} }, + async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + try { + await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); + await checkAndInitAssetCriticalityResources(context, logger); - const securitySolution = await context.securitySolution; - const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); + const securitySolution = await context.securitySolution; + const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); - const result = await assetCriticalityClient.getStatus(); + const result = await assetCriticalityClient.getStatus(); - securitySolution.getAuditLogger()?.log({ - message: 'User checked the status of the asset criticality service', - event: { - action: AssetCriticalityAuditActions.ASSET_CRITICALITY_STATUS_GET, - category: AUDIT_CATEGORY.DATABASE, - type: AUDIT_TYPE.ACCESS, - outcome: AUDIT_OUTCOME.UNKNOWN, - }, - }); + securitySolution.getAuditLogger()?.log({ + message: 'User checked the status of the asset criticality service', + event: { + action: AssetCriticalityAuditActions.ASSET_CRITICALITY_STATUS_GET, + category: AUDIT_CATEGORY.DATABASE, + type: AUDIT_TYPE.ACCESS, + outcome: AUDIT_OUTCOME.UNKNOWN, + }, + }); - const body: AssetCriticalityStatusResponse = { - asset_criticality_resources_installed: result.isAssetCriticalityResourcesInstalled, - }; - return response.ok({ - body, - }); - } catch (e) { - const error = transformError(e); + const body: AssetCriticalityStatusResponse = { + asset_criticality_resources_installed: result.isAssetCriticalityResourcesInstalled, + }; + return response.ok({ + body, + }); + } catch (e) { + const error = transformError(e); - return siemResponse.error({ - statusCode: error.statusCode, - body: { message: error.message, full_error: JSON.stringify(e) }, - bypassErrorFormat: true, - }); + return siemResponse.error({ + statusCode: error.statusCode, + body: { message: error.message, full_error: JSON.stringify(e) }, + bypassErrorFormat: true, + }); + } } - }); + ); }; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts index cf4123db487a4..bd0a64fb08da7 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts @@ -4,19 +4,22 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { Logger } from '@kbn/core/server'; +import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { schema } from '@kbn/config-schema'; import Papa from 'papaparse'; import { transformError } from '@kbn/securitysolution-es-utils'; +import type internal from 'stream'; import type { AssetCriticalityCsvUploadResponse } from '../../../../../common/api/entity_analytics'; import { CRITICALITY_CSV_MAX_SIZE_BYTES_WITH_TOLERANCE } from '../../../../../common/entity_analytics/asset_criticality'; import type { ConfigType } from '../../../../config'; -import type { HapiReadableStream } from '../../../../types'; +import type { HapiReadableStream, SecuritySolutionRequestHandlerContext } from '../../../../types'; import { - ASSET_CRITICALITY_CSV_UPLOAD_URL, + ASSET_CRITICALITY_INTERNAL_CSV_UPLOAD_URL, + ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, APP_ID, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; import { transformCSVToUpsertRecords } from '../transform_csv_to_upsert_records'; @@ -26,18 +29,109 @@ import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; -export const assetCriticalityCSVUploadRoute = ( +type CSVUploadHandler = ( + context: SecuritySolutionRequestHandlerContext, + request: { + body: { file: internal.Stream }; + }, + response: KibanaResponseFactory +) => Promise; + +const handler: ( + logger: Logger, + getStartServices: EntityAnalyticsRoutesDeps['getStartServices'], + config: ConfigType +) => CSVUploadHandler = (logger, getStartServices, config) => async (context, request, response) => { + const { errorRetries, maxBulkRequestBodySizeBytes } = + config.entityAnalytics.assetCriticality.csvUpload; + + const securitySolution = await context.securitySolution; + securitySolution.getAuditLogger()?.log({ + message: 'User attempted to assign many asset criticalities via file upload', + event: { + action: AssetCriticalityAuditActions.ASSET_CRITICALITY_BULK_UPDATE, + category: AUDIT_CATEGORY.DATABASE, + type: AUDIT_TYPE.CREATION, + outcome: AUDIT_OUTCOME.UNKNOWN, + }, + }); + + const start = new Date(); + const siemResponse = buildSiemResponse(response); + const [coreStart] = await getStartServices(); + const telemetry = coreStart.analytics; + + try { + await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); + await checkAndInitAssetCriticalityResources(context, logger); + const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); + const fileStream = request.body.file as HapiReadableStream; + + logger.debug(`Parsing asset criticality CSV file ${fileStream.hapi.filename}`); + + const csvStream = Papa.parse(Papa.NODE_STREAM_INPUT, { + header: false, + dynamicTyping: true, + skipEmptyLines: true, + }); + + const recordsStream = fileStream.pipe(csvStream).pipe(transformCSVToUpsertRecords()); + + const { errors, stats } = await assetCriticalityClient.bulkUpsertFromStream({ + recordsStream, + retries: errorRetries, + flushBytes: maxBulkRequestBodySizeBytes, + }); + const end = new Date(); + + const tookMs = end.getTime() - start.getTime(); + logger.debug(`Asset criticality CSV upload completed in ${tookMs}ms ${JSON.stringify(stats)}`); + + // type assignment here to ensure that the response body stays in sync with the API schema + const resBody: AssetCriticalityCsvUploadResponse = { errors, stats }; + + const [eventType, event] = createAssetCriticalityProcessedFileEvent({ + startTime: start, + endTime: end, + result: stats, + }); + + telemetry.reportEvent(eventType, event); + + return response.ok({ body: resBody }); + } catch (e) { + logger.error(`Error during asset criticality csv upload: ${e}`); + try { + const end = new Date(); + + const [eventType, event] = createAssetCriticalityProcessedFileEvent({ + startTime: start, + endTime: end, + }); + + telemetry.reportEvent(eventType, event); + } catch (error) { + logger.error(`Error reporting telemetry event: ${error}`); + } + + const error = transformError(e); + return siemResponse.error({ + statusCode: error.statusCode, + body: error.message, + }); + } +}; + +export const assetCriticalityInternalCSVUploadRoute = ( router: EntityAnalyticsRoutesDeps['router'], logger: Logger, config: ConfigType, getStartServices: EntityAnalyticsRoutesDeps['getStartServices'] ) => { - const { errorRetries, maxBulkRequestBodySizeBytes } = - config.entityAnalytics.assetCriticality.csvUpload; router.versioned .post({ access: 'internal', - path: ASSET_CRITICALITY_CSV_UPLOAD_URL, + path: ASSET_CRITICALITY_INTERNAL_CSV_UPLOAD_URL, options: { tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], body: { @@ -49,7 +143,7 @@ export const assetCriticalityCSVUploadRoute = ( }) .addVersion( { - version: '1', + version: API_VERSIONS.internal.v1, validate: { request: { body: schema.object({ @@ -58,84 +152,39 @@ export const assetCriticalityCSVUploadRoute = ( }, }, }, - async (context, request, response) => { - const securitySolution = await context.securitySolution; - securitySolution.getAuditLogger()?.log({ - message: 'User attempted to assign many asset criticalities via file upload', - event: { - action: AssetCriticalityAuditActions.ASSET_CRITICALITY_BULK_UPDATE, - category: AUDIT_CATEGORY.DATABASE, - type: AUDIT_TYPE.CREATION, - outcome: AUDIT_OUTCOME.UNKNOWN, + handler(logger, getStartServices, config) + ); +}; +export const assetCriticalityPublicCSVUploadRoute = ( + router: EntityAnalyticsRoutesDeps['router'], + logger: Logger, + config: ConfigType, + getStartServices: EntityAnalyticsRoutesDeps['getStartServices'] +) => { + router.versioned + .post({ + access: 'public', + path: ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, + options: { + tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], + body: { + output: 'stream', + accepts: 'multipart/form-data', + maxBytes: CRITICALITY_CSV_MAX_SIZE_BYTES_WITH_TOLERANCE, + }, + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + validate: { + request: { + body: schema.object({ + file: schema.stream(), + }), }, - }); - - const start = new Date(); - const siemResponse = buildSiemResponse(response); - const [coreStart] = await getStartServices(); - const telemetry = coreStart.analytics; - - try { - await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); - await checkAndInitAssetCriticalityResources(context, logger); - const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); - const fileStream = request.body.file as HapiReadableStream; - - logger.debug(`Parsing asset criticality CSV file ${fileStream.hapi.filename}`); - - const csvStream = Papa.parse(Papa.NODE_STREAM_INPUT, { - header: false, - dynamicTyping: true, - skipEmptyLines: true, - }); - - const recordsStream = fileStream.pipe(csvStream).pipe(transformCSVToUpsertRecords()); - - const { errors, stats } = await assetCriticalityClient.bulkUpsertFromStream({ - recordsStream, - retries: errorRetries, - flushBytes: maxBulkRequestBodySizeBytes, - }); - const end = new Date(); - - const tookMs = end.getTime() - start.getTime(); - logger.debug( - `Asset criticality CSV upload completed in ${tookMs}ms ${JSON.stringify(stats)}` - ); - - // type assignment here to ensure that the response body stays in sync with the API schema - const resBody: AssetCriticalityCsvUploadResponse = { errors, stats }; - - const [eventType, event] = createAssetCriticalityProcessedFileEvent({ - startTime: start, - endTime: end, - result: stats, - }); - - telemetry.reportEvent(eventType, event); - - return response.ok({ body: resBody }); - } catch (e) { - logger.error(`Error during asset criticality csv upload: ${e}`); - try { - const end = new Date(); - - const [eventType, event] = createAssetCriticalityProcessedFileEvent({ - startTime: start, - endTime: end, - }); - - telemetry.reportEvent(eventType, event); - } catch (error) { - logger.error(`Error reporting telemetry event: ${error}`); - } - - const error = transformError(e); - return siemResponse.error({ - statusCode: error.statusCode, - body: error.message, - }); - } - } + }, + }, + handler(logger, getStartServices, config) ); }; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts index 8a6d475695962..d367a1f8bd4d3 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts @@ -4,13 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { Logger } from '@kbn/core/server'; +import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import type { SecuritySolutionRequestHandlerContext } from '../../../../types'; import { - ASSET_CRITICALITY_URL, + ASSET_CRITICALITY_PUBLIC_URL, + ASSET_CRITICALITY_INTERNAL_URL, APP_ID, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; @@ -19,69 +22,106 @@ import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled'; -export const assetCriticalityUpsertRoute = ( + +type UpsertHandler = ( + context: SecuritySolutionRequestHandlerContext, + request: { + body: CreateAssetCriticalityRecord; + }, + response: KibanaResponseFactory +) => Promise; + +const handler: (logger: Logger) => UpsertHandler = + (logger) => async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + try { + await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); + await checkAndInitAssetCriticalityResources(context, logger); + + const securitySolution = await context.securitySolution; + const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); + + const assetCriticalityRecord = { + idField: request.body.id_field, + idValue: request.body.id_value, + criticalityLevel: request.body.criticality_level, + }; + + const result = await assetCriticalityClient.upsert( + assetCriticalityRecord, + request.body.refresh + ); + + securitySolution.getAuditLogger()?.log({ + message: 'User attempted to assign the asset criticality level for an entity', + event: { + action: AssetCriticalityAuditActions.ASSET_CRITICALITY_UPDATE, + category: AUDIT_CATEGORY.DATABASE, + type: AUDIT_TYPE.CREATION, + outcome: AUDIT_OUTCOME.UNKNOWN, + }, + }); + + return response.ok({ + body: result, + }); + } catch (e) { + const error = transformError(e); + + return siemResponse.error({ + statusCode: error.statusCode, + body: { message: error.message, full_error: JSON.stringify(e) }, + bypassErrorFormat: true, + }); + } + }; + +export const assetCriticalityInternalUpsertRoute = ( router: EntityAnalyticsRoutesDeps['router'], logger: Logger ) => { router.versioned .post({ access: 'internal', - path: ASSET_CRITICALITY_URL, + path: ASSET_CRITICALITY_INTERNAL_URL, options: { tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], }, }) .addVersion( { - version: '1', + version: API_VERSIONS.internal.v1, validate: { request: { body: buildRouteValidationWithZod(CreateAssetCriticalityRecord), }, }, }, - async (context, request, response) => { - const siemResponse = buildSiemResponse(response); - try { - await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); - await checkAndInitAssetCriticalityResources(context, logger); - - const securitySolution = await context.securitySolution; - const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); - - const assetCriticalityRecord = { - idField: request.body.id_field, - idValue: request.body.id_value, - criticalityLevel: request.body.criticality_level, - }; - - const result = await assetCriticalityClient.upsert( - assetCriticalityRecord, - request.body.refresh - ); - - securitySolution.getAuditLogger()?.log({ - message: 'User attempted to assign the asset criticality level for an entity', - event: { - action: AssetCriticalityAuditActions.ASSET_CRITICALITY_UPDATE, - category: AUDIT_CATEGORY.DATABASE, - type: AUDIT_TYPE.CREATION, - outcome: AUDIT_OUTCOME.UNKNOWN, - }, - }); - - return response.ok({ - body: result, - }); - } catch (e) { - const error = transformError(e); + handler(logger) + ); +}; - return siemResponse.error({ - statusCode: error.statusCode, - body: { message: error.message, full_error: JSON.stringify(e) }, - bypassErrorFormat: true, - }); - } - } +export const assetCriticalityPublicUpsertRoute = ( + router: EntityAnalyticsRoutesDeps['router'], + logger: Logger +) => { + router.versioned + .post({ + access: 'public', + path: ASSET_CRITICALITY_PUBLIC_URL, + options: { + tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + validate: { + request: { + body: buildRouteValidationWithZod(CreateAssetCriticalityRecord), + }, + }, + }, + handler(logger) ); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts index 3a46aa56ef614..da786269519db 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts @@ -11,11 +11,12 @@ import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; import { - ASSET_CRITICALITY_STATUS_URL, - ASSET_CRITICALITY_URL, - ASSET_CRITICALITY_PRIVILEGES_URL, - ASSET_CRITICALITY_CSV_UPLOAD_URL, + ASSET_CRITICALITY_PUBLIC_URL, + ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, + ASSET_CRITICALITY_INTERNAL_STATUS_URL, + ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL, ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, } from '@kbn/security-solution-plugin/common/constants'; import type { AssetCriticalityRecord } from '@kbn/security-solution-plugin/common/api/entity_analytics'; import type { Client } from '@elastic/elasticsearch'; @@ -109,9 +110,9 @@ export const assetCriticalityRouteHelpersFactory = ( ) => ({ status: async () => await supertest - .get(routeWithNamespace(ASSET_CRITICALITY_STATUS_URL, namespace)) + .get(routeWithNamespace(ASSET_CRITICALITY_INTERNAL_STATUS_URL, namespace)) .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send() .expect(200), @@ -120,9 +121,9 @@ export const assetCriticalityRouteHelpersFactory = ( { expectStatusCode }: { expectStatusCode: number } = { expectStatusCode: 200 } ) => await supertest - .post(routeWithNamespace(ASSET_CRITICALITY_URL, namespace)) + .post(routeWithNamespace(ASSET_CRITICALITY_PUBLIC_URL, namespace)) .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.public.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(body) .expect(expectStatusCode), @@ -132,11 +133,11 @@ export const assetCriticalityRouteHelpersFactory = ( { expectStatusCode }: { expectStatusCode: number } = { expectStatusCode: 200 } ) => { const qs = querystring.stringify({ id_field: idField, id_value: idValue }); - const route = `${routeWithNamespace(ASSET_CRITICALITY_URL, namespace)}?${qs}`; + const route = `${routeWithNamespace(ASSET_CRITICALITY_PUBLIC_URL, namespace)}?${qs}`; return supertest .delete(route) .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.public.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .expect(expectStatusCode); }, @@ -146,11 +147,11 @@ export const assetCriticalityRouteHelpersFactory = ( { expectStatusCode }: { expectStatusCode: number } = { expectStatusCode: 200 } ) => { const qs = querystring.stringify({ id_field: idField, id_value: idValue }); - const route = `${routeWithNamespace(ASSET_CRITICALITY_URL, namespace)}?${qs}`; + const route = `${routeWithNamespace(ASSET_CRITICALITY_PUBLIC_URL, namespace)}?${qs}`; return supertest .get(route) .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.public.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .expect(expectStatusCode); }, @@ -160,9 +161,9 @@ export const assetCriticalityRouteHelpersFactory = ( ) => { const file = fileContent instanceof Buffer ? fileContent : Buffer.from(fileContent); return supertest - .post(routeWithNamespace(ASSET_CRITICALITY_CSV_UPLOAD_URL, namespace)) + .post(routeWithNamespace(ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, namespace)) .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.public.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .attach('file', file, { filename: 'asset_criticality.csv' }) .expect(expectStatusCode); @@ -175,9 +176,9 @@ export const assetCriticalityRouteHelpersFactoryNoAuth = ( ) => ({ privilegesForUser: async ({ username, password }: { username: string; password: string }) => await supertestWithoutAuth - .get(ASSET_CRITICALITY_PRIVILEGES_URL) + .get(ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL) .auth(username, password) - .set('elastic-api-version', '1') + .set('elastic-api-version', API_VERSIONS.internal.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send() .expect(200), From 051b91a47ffcbf68a01bdae869375bcd4c8fe610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Tue, 18 Jun 2024 12:18:07 +0200 Subject: [PATCH 041/127] [Discover] Add logs source and document contexts (#184601) ## :memo: Summary This PR adds basic implementations for resolving "logs" data source and document contexts to their respective profiles. Due to the limited set of profile customization points the new profiles are empty. - closes #184079 - closes #184080 ## :mag: Implementation details - In order to organize these and future profiles this PR introduces the `profile_providers` folder in `context_awareness`. - For a more structured organization, utilities for resolving logs sources have been moved/implemented in the `@kbn/discover-utils` and `@kbn/data-view-utils` packages. - The code ownership for the two logs profiles is shared between the data discovery team and the obs ux logs team. ### Document Level Logs Resolution The document logs context resolution is performed with the following criteria, as far as one complies, the context will be evaluated as a match: - The `data_stream.type` field exists on the document and it's equal to `logs` - The document contains any field from the [ECS Log field set](https://www.elastic.co/guide/en/ecs/current/ecs-log.html) (fields staring with `log.`) - The `_index` field exists and tests positive against the allowed indices from the [built-in definition/ settings](https://github.com/elastic/kibana/pull/184601/files#diff-5e1646fa4ec758a92aa38910dc047b18cb826e287a36b43e811eb5fc7a3b0fe9R28). ### Data Source Logs Resolution The data source logs context resolution is performed with the following criteria, as far as one complies, the context will be evaluated as a match: - Being the source of a data view type, the related index tests positive against the allowed indices from the [built-in definition/ settings](https://github.com/elastic/kibana/pull/184601/files#diff-5e1646fa4ec758a92aa38910dc047b18cb826e287a36b43e811eb5fc7a3b0fe9R28). - Being the source of a ES|QL query type, the related index extracted from the query tests positive against the allowed indices from the [built-in definition/ settings](https://github.com/elastic/kibana/pull/184601/files#diff-5e1646fa4ec758a92aa38910dc047b18cb826e287a36b43e811eb5fc7a3b0fe9R28). ## :female_detective: Review notes > [!NOTE] > Notes in this format have been left through the PR to give additional context about some choices, any further feedback is welcome --------- Co-authored-by: Davis McPhee Co-authored-by: Marco Antonio Ghiani Co-authored-by: Marco Antonio Ghiani Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kerry Gallagher --- packages/kbn-data-view-utils/index.ts | 3 + .../utils/create_regexp_pattern_from.test.ts | 68 +++++++ .../src/utils/create_regexp_pattern_from.ts | 12 +- .../test_pattern_against_allowed_list.test.ts | 24 +++ .../test_pattern_against_allowed_list.ts | 22 +++ packages/kbn-discover-utils/index.ts | 4 + .../src/data_types/logs/index.ts | 2 + .../data_types/logs/logs_context_service.ts | 45 +++++ packages/kbn-discover-utils/tsconfig.json | 1 + .../discover/common/data_sources/utils.ts | 8 + src/plugins/discover/public/build_services.ts | 2 +- .../context_awareness/__mocks__/index.ts | 4 + .../log_document_profile/index.ts | 9 + .../log_document_profile/profile.test.ts | 78 ++++++++ .../log_document_profile/profile.ts | 57 ++++++ .../logs_data_source_profile/index.ts | 9 + .../logs_data_source_profile/profile.test.ts | 78 ++++++++ .../logs_data_source_profile/profile.ts | 50 +++++ .../profiles/profile_provider_services.ts | 27 +++ src/plugins/discover/public/index.ts | 2 +- src/plugins/discover/public/plugin.tsx | 176 ++---------------- src/plugins/discover/public/types.ts | 170 +++++++++++++++++ .../utils/initialize_kbn_url_tracking.test.ts | 2 +- .../utils/initialize_kbn_url_tracking.ts | 2 +- .../apm/public/plugin.ts | 2 +- .../logs_explorer/common/constants.ts | 3 - .../data_views/models/data_view_descriptor.ts | 30 +-- .../logs_explorer/common/ui_settings.ts | 4 +- .../logs_explorer/tsconfig.json | 1 + .../data_source_selector.ts | 2 +- 30 files changed, 696 insertions(+), 201 deletions(-) create mode 100644 packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts rename x-pack/plugins/observability_solution/logs_explorer/common/data_views/utils.ts => packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts (52%) create mode 100644 packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.test.ts create mode 100644 packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.ts create mode 100644 packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/index.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.test.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/index.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.test.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts create mode 100644 src/plugins/discover/public/context_awareness/profiles/profile_provider_services.ts create mode 100644 src/plugins/discover/public/types.ts diff --git a/packages/kbn-data-view-utils/index.ts b/packages/kbn-data-view-utils/index.ts index c78869a471cb0..1c881dbdacf79 100644 --- a/packages/kbn-data-view-utils/index.ts +++ b/packages/kbn-data-view-utils/index.ts @@ -7,3 +7,6 @@ */ export * from './src/constants'; + +export { createRegExpPatternFrom } from './src/utils/create_regexp_pattern_from'; +export { testPatternAgainstAllowedList } from './src/utils/test_pattern_against_allowed_list'; diff --git a/packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts b/packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts new file mode 100644 index 0000000000000..24975576582d6 --- /dev/null +++ b/packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { createRegExpPatternFrom } from './create_regexp_pattern_from'; + +describe('createRegExpPatternFrom should create a regular expression starting from a string that', () => { + const regExpPattern = createRegExpPatternFrom('logs'); + + it('tests positive for single index patterns starting with the passed base pattern', () => { + expect('logs*').toMatch(regExpPattern); + expect('logs-*').toMatch(regExpPattern); + expect('logs-*-*').toMatch(regExpPattern); + expect('logs-system.syslog-*').toMatch(regExpPattern); + + expect('logss*').not.toMatch(regExpPattern); + expect('logss-*').not.toMatch(regExpPattern); + expect('metrics*').not.toMatch(regExpPattern); + expect('metrics-*').not.toMatch(regExpPattern); + }); + + it('tests positive for single index patterns containing the passed base pattern', () => { + expect('foo-logs*').toMatch(regExpPattern); + expect('foo-logs-*').toMatch(regExpPattern); + expect('foo-logs-*-*').toMatch(regExpPattern); + expect('foo-logs-system.syslog-*').toMatch(regExpPattern); + expect('.ds-kibana_sample_data_logs-2024.06.13-000001').toMatch(regExpPattern); + + expect('foo-logss*').not.toMatch(regExpPattern); + expect('foo-logss-*').not.toMatch(regExpPattern); + expect('foo-metrics*').not.toMatch(regExpPattern); + expect('foo-metrics-*').not.toMatch(regExpPattern); + }); + + it('tests positive for single index patterns with CCS prefixes', () => { + expect('cluster1:logs-*').toMatch(regExpPattern); + expect('cluster1:logs-*-*').toMatch(regExpPattern); + expect('cluster1:logs-system.syslog-*').toMatch(regExpPattern); + expect('cluster1:logs-system.syslog-default').toMatch(regExpPattern); + + expect('cluster1:logss*').not.toMatch(regExpPattern); + expect('cluster1:logss-*').not.toMatch(regExpPattern); + expect('cluster1:metrics*').not.toMatch(regExpPattern); + expect('cluster1:metrics-*').not.toMatch(regExpPattern); + }); + + it('tests positive for multiple index patterns comma-separated if all of them individually match the criteria', () => { + expect('logs-*,cluster1:logs-*').toMatch(regExpPattern); + expect('cluster1:logs-*,cluster2:logs-*').toMatch(regExpPattern); + expect('*:logs-system.syslog-*,*:logs-system.errors-*').toMatch(regExpPattern); + + expect('*:metrics-system.syslog-*,logs-system.errors-*').not.toMatch(regExpPattern); + }); + + it('tests positive for patterns with trailing commas', () => { + expect('logs-*,').toMatch(regExpPattern); + expect('cluster1:logs-*,logs-*,').toMatch(regExpPattern); + }); + + it('tests negative for patterns with spaces and unexpected commas', () => { + expect('cluster1:logs-*,clust,er2:logs-*').not.toMatch(regExpPattern); + expect('cluster1:logs-*, cluster2:logs-*').not.toMatch(regExpPattern); + }); +}); diff --git a/x-pack/plugins/observability_solution/logs_explorer/common/data_views/utils.ts b/packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts similarity index 52% rename from x-pack/plugins/observability_solution/logs_explorer/common/data_views/utils.ts rename to packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts index 4b316ba1d5877..c240f2f893688 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/common/data_views/utils.ts +++ b/packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts @@ -1,15 +1,17 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ -export const buildIndexPatternRegExp = (basePatterns: string[]) => { +export const createRegExpPatternFrom = (basePatterns: string | string[]) => { + const patterns = Array.isArray(basePatterns) ? basePatterns : [basePatterns]; // Create the base patterns union with strict boundaries - const basePatternGroup = `\\b(${basePatterns.join('|')})\\b([^,\\s]+)?`; + const basePatternGroup = `[^,\\s]*(\\b|_)(${patterns.join('|')})(\\b|_)([^,\\s]*)?`; // Apply base patterns union for local and remote clusters - const localAndRemotePatternGroup = `((${basePatternGroup})|([^:,\\s]+:${basePatternGroup}))`; + const localAndRemotePatternGroup = `((${basePatternGroup})|([^:,\\s]*:${basePatternGroup}))`; // Handle trailing comma and multiple pattern concatenation return new RegExp(`^${localAndRemotePatternGroup}(,${localAndRemotePatternGroup})*(,$|$)`, 'i'); }; diff --git a/packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.test.ts b/packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.test.ts new file mode 100644 index 0000000000000..e72038771b036 --- /dev/null +++ b/packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.test.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 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 { testPatternAgainstAllowedList } from './test_pattern_against_allowed_list'; + +describe('testPatternAgainstAllowedList', () => { + const allowedList = ['foo-logs-bar', /^\b(logs)\b([^,\s]*)/i]; + + it('should return true if the passed input matches any string or regexp of the passed list', () => { + expect(testPatternAgainstAllowedList(allowedList)('logs-*')).toBeTruthy(); + expect(testPatternAgainstAllowedList(allowedList)('logs-*-*')).toBeTruthy(); + expect(testPatternAgainstAllowedList(allowedList)('logs-system.syslog-*')).toBeTruthy(); + expect(testPatternAgainstAllowedList(allowedList)('foo-logs-bar')).toBeTruthy(); + + expect(testPatternAgainstAllowedList(allowedList)('logss-*')).toBeFalsy(); + expect(testPatternAgainstAllowedList(allowedList)('metrics*')).toBeFalsy(); + expect(testPatternAgainstAllowedList(allowedList)('metrics-*')).toBeFalsy(); + }); +}); diff --git a/packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.ts b/packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.ts new file mode 100644 index 0000000000000..62cbd4db9d0fe --- /dev/null +++ b/packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const testPatternAgainstAllowedList = + (allowedList: Array) => (value: string) => { + for (const allowedItem of allowedList) { + const isMatchingString = typeof allowedItem === 'string' && value === allowedItem; + const isMatchingRegExp = allowedItem instanceof RegExp && allowedItem.test(value); + + if (isMatchingString || isMatchingRegExp) { + return true; + } + } + + // If no match is found in the allowedList, return false + return false; + }; diff --git a/packages/kbn-discover-utils/index.ts b/packages/kbn-discover-utils/index.ts index 7a7fedfb5f1e3..1656a36a91da2 100644 --- a/packages/kbn-discover-utils/index.ts +++ b/packages/kbn-discover-utils/index.ts @@ -10,6 +10,7 @@ export { CONTEXT_DEFAULT_SIZE_SETTING, CONTEXT_STEP_SETTING, CONTEXT_TIE_BREAKER_FIELDS_SETTING, + DEFAULT_ALLOWED_LOGS_BASE_PATTERNS, DEFAULT_COLUMNS_SETTING, DOC_HIDE_TIME_COLUMN_SETTING, DOC_TABLE_LEGACY, @@ -30,6 +31,7 @@ export { IgnoredReason, buildDataTableRecord, buildDataTableRecordList, + createLogsContextService, fieldConstants, formatFieldValue, formatHit, @@ -43,4 +45,6 @@ export { usePager, } from './src'; +export type { LogsContextService } from './src'; + export * from './src/types'; diff --git a/packages/kbn-discover-utils/src/data_types/logs/index.ts b/packages/kbn-discover-utils/src/data_types/logs/index.ts index 21d54fd754a3e..f1147d7aa071b 100644 --- a/packages/kbn-discover-utils/src/data_types/logs/index.ts +++ b/packages/kbn-discover-utils/src/data_types/logs/index.ts @@ -8,3 +8,5 @@ export * from './types'; export * from './utils'; + +export * from './logs_context_service'; diff --git a/packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts b/packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts new file mode 100644 index 0000000000000..6eecd1beff491 --- /dev/null +++ b/packages/kbn-discover-utils/src/data_types/logs/logs_context_service.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 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 { createRegExpPatternFrom, testPatternAgainstAllowedList } from '@kbn/data-view-utils'; + +export interface LogsContextService { + isLogsIndexPattern(indexPattern: unknown): boolean; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface LogsContextServiceDeps { + // We will probably soon add uiSettings as a dependency + // to consume user configured indices +} + +export const DEFAULT_ALLOWED_LOGS_BASE_PATTERNS = [ + 'log', + 'logs', + 'logstash', + 'auditbeat', + 'filebeat', + 'winlogbeat', +]; + +export const createLogsContextService = (_deps: LogsContextServiceDeps = {}) => { + // This is initially an hard-coded set of well-known base patterns, + // we can extend this allowed list with any setting coming from uiSettings + const ALLOWED_LOGS_DATA_SOURCES = [createRegExpPatternFrom(DEFAULT_ALLOWED_LOGS_BASE_PATTERNS)]; + + const isLogsIndexPattern = (indexPattern: unknown) => { + return ( + typeof indexPattern === 'string' && + testPatternAgainstAllowedList(ALLOWED_LOGS_DATA_SOURCES)(indexPattern) + ); + }; + + return { + isLogsIndexPattern, + }; +}; diff --git a/packages/kbn-discover-utils/tsconfig.json b/packages/kbn-discover-utils/tsconfig.json index 64453f8245afe..bbd35127c43fb 100644 --- a/packages/kbn-discover-utils/tsconfig.json +++ b/packages/kbn-discover-utils/tsconfig.json @@ -18,6 +18,7 @@ "kbn_references": [ "@kbn/data-service", "@kbn/data-views-plugin", + "@kbn/data-view-utils", "@kbn/es-query", "@kbn/field-formats-plugin", "@kbn/field-types", diff --git a/src/plugins/discover/common/data_sources/utils.ts b/src/plugins/discover/common/data_sources/utils.ts index 4bf8b0fcf3678..f876d0b4c06f2 100644 --- a/src/plugins/discover/common/data_sources/utils.ts +++ b/src/plugins/discover/common/data_sources/utils.ts @@ -25,3 +25,11 @@ export const isDataSourceType = ( dataSource: DiscoverDataSource | undefined, type: T ): dataSource is Extract => dataSource?.type === type; + +export const isDataViewSource = ( + dataSource: DiscoverDataSource | undefined +): dataSource is DataViewDataSource => isDataSourceType(dataSource, DataSourceType.DataView); + +export const isEsqlSource = ( + dataSource: DiscoverDataSource | undefined +): dataSource is EsqlDataSource => isDataSourceType(dataSource, DataSourceType.Esql); diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index 519d6a36fb528..e1ccef0105d48 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -56,7 +56,7 @@ import { memoize, noop } from 'lodash'; import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; -import type { DiscoverStartPlugins } from './plugin'; +import type { DiscoverStartPlugins } from './types'; import type { DiscoverContextAppLocator } from './application/context/services/locator'; import type { DiscoverSingleDocLocator } from './application/doc/locator'; import type { DiscoverAppLocator } from '../common'; diff --git a/src/plugins/discover/public/context_awareness/__mocks__/index.ts b/src/plugins/discover/public/context_awareness/__mocks__/index.ts index b493ff43bfbca..0e104b6a02636 100644 --- a/src/plugins/discover/public/context_awareness/__mocks__/index.ts +++ b/src/plugins/discover/public/context_awareness/__mocks__/index.ts @@ -19,6 +19,7 @@ import { RootProfileService, SolutionType, } from '../profiles'; +import { createProfileProviderServices } from '../profiles/profile_provider_services'; import { ProfilesManager } from '../profiles_manager'; export const createContextAwarenessMocks = () => { @@ -107,6 +108,8 @@ export const createContextAwarenessMocks = () => { documentProfileServiceMock ); + const profileProviderServices = createProfileProviderServices(); + return { rootProfileProviderMock, dataSourceProfileProviderMock, @@ -114,5 +117,6 @@ export const createContextAwarenessMocks = () => { contextRecordMock, contextRecordMock2, profilesManagerMock, + profileProviderServices, }; }; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/index.ts new file mode 100644 index 0000000000000..c31d26b4a8989 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/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 { createLogDocumentProfileProvider } from './profile'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.test.ts b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.test.ts new file mode 100644 index 0000000000000..6514eb699e553 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.test.ts @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { buildDataTableRecord } from '@kbn/discover-utils'; +import { DocumentType } from '../../profiles'; +import { createContextAwarenessMocks } from '../../__mocks__'; +import { createLogDocumentProfileProvider } from './profile'; + +const mockServices = createContextAwarenessMocks().profileProviderServices; + +describe('logDocumentProfileProvider', () => { + const logDocumentProfileProvider = createLogDocumentProfileProvider(mockServices); + const RESOLUTION_MATCH = { + isMatch: true, + context: { + type: DocumentType.Log, + }, + }; + const RESOLUTION_MISMATCH = { + isMatch: false, + }; + + it('matches records with the correct data stream type', () => { + expect( + logDocumentProfileProvider.resolve({ + record: buildMockRecord('logs-2000-01-01', { + 'data_stream.type': ['logs'], + }), + }) + ).toEqual(RESOLUTION_MATCH); + }); + + it('matches records with fields prefixed with "log."', () => { + expect( + logDocumentProfileProvider.resolve({ + record: buildMockRecord('logs-2000-01-01', { + 'log.level': ['INFO'], + }), + }) + ).toEqual(RESOLUTION_MATCH); + }); + + it('matches records with indices matching the allowed pattern', () => { + expect( + logDocumentProfileProvider.resolve({ + record: buildMockRecord('logs-2000-01-01'), + }) + ).toEqual(RESOLUTION_MATCH); + expect( + logDocumentProfileProvider.resolve({ + record: buildMockRecord('remote_cluster:filebeat'), + }) + ).toEqual(RESOLUTION_MATCH); + }); + + it('does not match records with neither characteristic', () => { + expect( + logDocumentProfileProvider.resolve({ + record: buildMockRecord('another-index'), + }) + ).toEqual(RESOLUTION_MISMATCH); + }); +}); + +const buildMockRecord = (index: string, fields: Record = {}) => + buildDataTableRecord({ + _id: '', + _index: index, + fields: { + _index: index, + ...fields, + }, + }); diff --git a/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts new file mode 100644 index 0000000000000..7c1da0cef45cd --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.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 { DataTableRecord } from '@kbn/discover-utils'; +import { DocumentProfileProvider, DocumentType } from '../../profiles'; +import { ProfileProviderServices } from '../../profiles/profile_provider_services'; + +export const createLogDocumentProfileProvider = ( + services: ProfileProviderServices +): DocumentProfileProvider => ({ + profileId: 'log-document-profile', + profile: {}, + resolve: ({ record }) => { + const isLogRecord = getIsLogRecord(record, services.logsContextService.isLogsIndexPattern); + + if (!isLogRecord) { + return { isMatch: false }; + } + + return { + isMatch: true, + context: { + type: DocumentType.Log, + }, + }; + }, +}); + +const getIsLogRecord = ( + record: DataTableRecord, + isLogsIndexPattern: ProfileProviderServices['logsContextService']['isLogsIndexPattern'] +) => { + return ( + getDataStreamType(record).includes('logs') || + hasFieldsWithPrefix('log.')(record) || + getIndices(record).some(isLogsIndexPattern) + ); +}; + +const getFieldValues = + (field: string) => + (record: DataTableRecord): unknown[] => { + const value = record.flattened[field]; + return Array.isArray(value) ? value : [value]; + }; + +const getDataStreamType = getFieldValues('data_stream.type'); +const getIndices = getFieldValues('_index'); + +const hasFieldsWithPrefix = (prefix: string) => (record: DataTableRecord) => { + return Object.keys(record.flattened).some((field) => field.startsWith(prefix)); +}; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/index.ts new file mode 100644 index 0000000000000..f7d780da6ef02 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/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 { createLogsDataSourceProfileProvider } from './profile'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.test.ts b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.test.ts new file mode 100644 index 0000000000000..e6b99802235cf --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.test.ts @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { createStubIndexPattern } from '@kbn/data-views-plugin/common/data_view.stub'; +import { createDataViewDataSource, createEsqlDataSource } from '../../../../common/data_sources'; +import { DataSourceCategory } from '../../profiles'; +import { createContextAwarenessMocks } from '../../__mocks__'; +import { createLogsDataSourceProfileProvider } from './profile'; + +const mockServices = createContextAwarenessMocks().profileProviderServices; + +describe('logsDataSourceProfileProvider', () => { + const logsDataSourceProfileProvider = createLogsDataSourceProfileProvider(mockServices); + const VALID_INDEX_PATTERN = 'logs-nginx.access-*'; + const MIXED_INDEX_PATTERN = 'logs-nginx.access-*,metrics-*'; + const INVALID_INDEX_PATTERN = 'my_source-access-*'; + + const RESOLUTION_MATCH = { + isMatch: true, + context: { category: DataSourceCategory.Logs }, + }; + const RESOLUTION_MISMATCH = { + isMatch: false, + }; + + it('should match ES|QL sources with an allowed index pattern in its query', () => { + expect( + logsDataSourceProfileProvider.resolve({ + dataSource: createEsqlDataSource(), + query: { esql: `from ${VALID_INDEX_PATTERN}` }, + }) + ).toEqual(RESOLUTION_MATCH); + }); + + it('should NOT match ES|QL sources with a mixed or not allowed index pattern in its query', () => { + expect( + logsDataSourceProfileProvider.resolve({ + dataSource: createEsqlDataSource(), + query: { esql: `from ${INVALID_INDEX_PATTERN}` }, + }) + ).toEqual(RESOLUTION_MISMATCH); + expect( + logsDataSourceProfileProvider.resolve({ + dataSource: createEsqlDataSource(), + query: { esql: `from ${MIXED_INDEX_PATTERN}` }, + }) + ).toEqual(RESOLUTION_MISMATCH); + }); + + it('should match data view sources with an allowed index pattern', () => { + expect( + logsDataSourceProfileProvider.resolve({ + dataSource: createDataViewDataSource({ dataViewId: VALID_INDEX_PATTERN }), + dataView: createStubIndexPattern({ spec: { title: VALID_INDEX_PATTERN } }), + }) + ).toEqual(RESOLUTION_MATCH); + }); + + it('should NOT match data view sources with a mixed or not allowed index pattern', () => { + expect( + logsDataSourceProfileProvider.resolve({ + dataSource: createDataViewDataSource({ dataViewId: INVALID_INDEX_PATTERN }), + dataView: createStubIndexPattern({ spec: { title: INVALID_INDEX_PATTERN } }), + }) + ).toEqual(RESOLUTION_MISMATCH); + expect( + logsDataSourceProfileProvider.resolve({ + dataSource: createDataViewDataSource({ dataViewId: MIXED_INDEX_PATTERN }), + dataView: createStubIndexPattern({ spec: { title: MIXED_INDEX_PATTERN } }), + }) + ).toEqual(RESOLUTION_MISMATCH); + }); +}); diff --git a/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts new file mode 100644 index 0000000000000..1ce42c6d1ffd1 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.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 { isOfAggregateQueryType } from '@kbn/es-query'; +import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; +import { isDataViewSource, isEsqlSource } from '../../../../common/data_sources'; +import { + DataSourceCategory, + DataSourceProfileProvider, + DataSourceProfileProviderParams, +} from '../../profiles'; +import { ProfileProviderServices } from '../../profiles/profile_provider_services'; + +export const createLogsDataSourceProfileProvider = ( + services: ProfileProviderServices +): DataSourceProfileProvider => ({ + profileId: 'logs-data-source-profile', + profile: {}, + resolve: (params) => { + const indexPattern = extractIndexPatternFrom(params); + + if (!services.logsContextService.isLogsIndexPattern(indexPattern)) { + return { isMatch: false }; + } + + return { + isMatch: true, + context: { category: DataSourceCategory.Logs }, + }; + }, +}); + +const extractIndexPatternFrom = ({ + dataSource, + dataView, + query, +}: DataSourceProfileProviderParams) => { + if (isEsqlSource(dataSource) && isOfAggregateQueryType(query)) { + return getIndexPatternFromESQLQuery(query.esql); + } else if (isDataViewSource(dataSource) && dataView) { + return dataView.getIndexPattern(); + } + + return null; +}; diff --git a/src/plugins/discover/public/context_awareness/profiles/profile_provider_services.ts b/src/plugins/discover/public/context_awareness/profiles/profile_provider_services.ts new file mode 100644 index 0000000000000..eced97659ecfa --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profiles/profile_provider_services.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { createLogsContextService, LogsContextService } from '@kbn/discover-utils'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface ProfileProviderDeps { + // We will probably soon add uiSettings as a dependency + // to consume user configured indices +} + +export interface ProfileProviderServices { + logsContextService: LogsContextService; +} + +export const createProfileProviderServices = ( + _deps: ProfileProviderDeps = {} +): ProfileProviderServices => { + return { + logsContextService: createLogsContextService(), + }; +}; diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index a2ce384dd0e60..bd88c4d6dbe09 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -9,7 +9,7 @@ import type { PluginInitializerContext } from '@kbn/core/public'; import { DiscoverPlugin } from './plugin'; -export type { DiscoverSetup, DiscoverStart } from './plugin'; +export type { DiscoverSetup, DiscoverStart } from './types'; export function plugin(initializerContext: PluginInitializerContext) { return new DiscoverPlugin(initializerContext); } diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index 7228070fe2d2c..4f1ae2a32634e 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { ComponentType } from 'react'; +import React from 'react'; import { BehaviorSubject, map, Observable } from 'rxjs'; import { AppMountParameters, @@ -17,42 +17,10 @@ import { PluginInitializerContext, ScopedHistory, } from '@kbn/core/public'; -import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { ExpressionsSetup, ExpressionsStart } from '@kbn/expressions-plugin/public'; -import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; -import { ChartsPluginStart } from '@kbn/charts-plugin/public'; -import type { GlobalSearchPluginSetup } from '@kbn/global-search-plugin/public'; -import { NavigationPublicPluginStart as NavigationStart } from '@kbn/navigation-plugin/public'; -import { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public'; -import { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; -import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; -import { Start as InspectorPublicPluginStart } from '@kbn/inspector-plugin/public'; -import { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; import { ENABLE_ESQL } from '@kbn/esql-utils'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; -import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; -import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; -import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; -import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; -import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; -import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public'; -import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; -import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public'; -import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; -import type { UnifiedDocViewerStart } from '@kbn/unified-doc-viewer-plugin/public'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; -import type { LensPublicStart } from '@kbn/lens-plugin/public'; import { TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils'; -import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; -import type { - ObservabilityAIAssistantPublicSetup, - ObservabilityAIAssistantPublicStart, -} from '@kbn/observability-ai-assistant-plugin/public'; -import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; -import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; import { PLUGIN_ID } from '../common'; import { registerFeature } from './register_feature'; import { buildServices, UrlTracker } from './build_services'; @@ -88,132 +56,10 @@ import { ProfilesManager, RootProfileService, } from './context_awareness'; - -/** - * @public - */ -export interface DiscoverSetup { - /** - * `share` plugin URL locator for Discover app. Use it to generate links into - * Discover application, for example, navigate: - * - * ```ts - * await plugins.discover.locator.navigate({ - * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', - * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', - * timeRange: { - * to: 'now', - * from: 'now-15m', - * mode: 'relative', - * }, - * }); - * ``` - * - * Generate a location: - * - * ```ts - * const location = await plugins.discover.locator.getLocation({ - * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', - * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', - * timeRange: { - * to: 'now', - * from: 'now-15m', - * mode: 'relative', - * }, - * }); - * ``` - */ - readonly locator: undefined | DiscoverAppLocator; - readonly showInlineTopNav: () => void; - readonly configureInlineTopNav: ( - projectNavId: string, - options: DiscoverCustomizationContext['inlineTopNav'] - ) => void; -} - -export interface DiscoverStart { - /** - * `share` plugin URL locator for Discover app. Use it to generate links into - * Discover application, for example, navigate: - * - * ```ts - * await plugins.discover.locator.navigate({ - * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', - * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', - * timeRange: { - * to: 'now', - * from: 'now-15m', - * mode: 'relative', - * }, - * }); - * ``` - * - * Generate a location: - * - * ```ts - * const location = await plugins.discover.locator.getLocation({ - * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', - * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', - * timeRange: { - * to: 'now', - * from: 'now-15m', - * mode: 'relative', - * }, - * }); - * ``` - */ - readonly locator: undefined | DiscoverAppLocator; - readonly DiscoverContainer: ComponentType; -} - -/** - * @internal - */ -export interface DiscoverSetupPlugins { - dataViews: DataViewsServicePublic; - share?: SharePluginSetup; - uiActions: UiActionsSetup; - embeddable: EmbeddableSetup; - urlForwarding: UrlForwardingSetup; - home?: HomePublicPluginSetup; - data: DataPublicPluginSetup; - expressions: ExpressionsSetup; - globalSearch?: GlobalSearchPluginSetup; - observabilityAIAssistant?: ObservabilityAIAssistantPublicSetup; -} - -/** - * @internal - */ -export interface DiscoverStartPlugins { - aiops?: AiopsPluginStart; - dataViews: DataViewsServicePublic; - dataViewEditor: DataViewEditorStart; - dataVisualizer?: DataVisualizerPluginStart; - uiActions: UiActionsStart; - embeddable: EmbeddableStart; - navigation: NavigationStart; - charts: ChartsPluginStart; - data: DataPublicPluginStart; - fieldFormats: FieldFormatsStart; - share?: SharePluginStart; - urlForwarding: UrlForwardingStart; - inspector: InspectorPublicPluginStart; - usageCollection?: UsageCollectionSetup; - dataViewFieldEditor: IndexPatternFieldEditorStart; - spaces?: SpacesPluginStart; - triggersActionsUi: TriggersAndActionsUIPublicPluginStart; - expressions: ExpressionsStart; - savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart; - savedObjectsManagement: SavedObjectsManagementPluginStart; - savedSearch: SavedSearchPublicPluginStart; - unifiedSearch: UnifiedSearchPublicPluginStart; - unifiedDocViewer: UnifiedDocViewerStart; - lens: LensPublicStart; - contentManagement: ContentManagementPublicStart; - noDataPage?: NoDataPagePluginStart; - observabilityAIAssistant?: ObservabilityAIAssistantPublicStart; -} +import { createProfileProviderServices } from './context_awareness/profiles/profile_provider_services'; +import { DiscoverSetup, DiscoverSetupPlugins, DiscoverStart, DiscoverStartPlugins } from './types'; +import { createLogsDataSourceProfileProvider } from './context_awareness/profile_providers/logs_data_source_profile'; +import { createLogDocumentProfileProvider } from './context_awareness/profile_providers/log_document_profile'; /** * Contains Discover, one of the oldest parts of Kibana @@ -459,10 +305,14 @@ export class DiscoverPlugin } private registerProfiles() { - // TODO: Conditionally register example profiles for functional testing in a follow up PR - // this.rootProfileService.registerProvider(o11yRootProfileProvider); - // this.dataSourceProfileService.registerProvider(logsDataSourceProfileProvider); - // this.documentProfileService.registerProvider(logDocumentProfileProvider); + const providerServices = createProfileProviderServices(); + + this.dataSourceProfileService.registerProvider( + createLogsDataSourceProfileProvider(providerServices) + ); + this.documentProfileService.registerProvider( + createLogDocumentProfileProvider(providerServices) + ); } private createProfilesManager() { diff --git a/src/plugins/discover/public/types.ts b/src/plugins/discover/public/types.ts new file mode 100644 index 0000000000000..54291a36a989b --- /dev/null +++ b/src/plugins/discover/public/types.ts @@ -0,0 +1,170 @@ +/* + * Copyright 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 { ComponentType } from 'react'; +import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import { ExpressionsSetup, ExpressionsStart } from '@kbn/expressions-plugin/public'; +import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; +import { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import type { GlobalSearchPluginSetup } from '@kbn/global-search-plugin/public'; +import { NavigationPublicPluginStart as NavigationStart } from '@kbn/navigation-plugin/public'; +import { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public'; +import { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; +import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; +import { Start as InspectorPublicPluginStart } from '@kbn/inspector-plugin/public'; +import { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; +import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; +import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; +import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; +import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; +import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; +import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public'; +import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; +import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public'; +import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { UnifiedDocViewerStart } from '@kbn/unified-doc-viewer-plugin/public'; +import type { LensPublicStart } from '@kbn/lens-plugin/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; +import type { + ObservabilityAIAssistantPublicSetup, + ObservabilityAIAssistantPublicStart, +} from '@kbn/observability-ai-assistant-plugin/public'; +import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; +import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; +import { DiscoverAppLocator } from '../common'; +import { DiscoverCustomizationContext } from './customizations'; +import { type DiscoverContainerProps } from './components/discover_container'; + +/** + * @public + */ +export interface DiscoverSetup { + /** + * `share` plugin URL locator for Discover app. Use it to generate links into + * Discover application, for example, navigate: + * + * ```ts + * await plugins.discover.locator.navigate({ + * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', + * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', + * timeRange: { + * to: 'now', + * from: 'now-15m', + * mode: 'relative', + * }, + * }); + * ``` + * + * Generate a location: + * + * ```ts + * const location = await plugins.discover.locator.getLocation({ + * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', + * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', + * timeRange: { + * to: 'now', + * from: 'now-15m', + * mode: 'relative', + * }, + * }); + * ``` + */ + readonly locator: undefined | DiscoverAppLocator; + readonly showInlineTopNav: () => void; + readonly configureInlineTopNav: ( + projectNavId: string, + options: DiscoverCustomizationContext['inlineTopNav'] + ) => void; +} + +export interface DiscoverStart { + /** + * `share` plugin URL locator for Discover app. Use it to generate links into + * Discover application, for example, navigate: + * + * ```ts + * await plugins.discover.locator.navigate({ + * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', + * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', + * timeRange: { + * to: 'now', + * from: 'now-15m', + * mode: 'relative', + * }, + * }); + * ``` + * + * Generate a location: + * + * ```ts + * const location = await plugins.discover.locator.getLocation({ + * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', + * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', + * timeRange: { + * to: 'now', + * from: 'now-15m', + * mode: 'relative', + * }, + * }); + * ``` + */ + readonly locator: undefined | DiscoverAppLocator; + readonly DiscoverContainer: ComponentType; +} + +/** + * @internal + */ +export interface DiscoverSetupPlugins { + data: DataPublicPluginSetup; + dataViews: DataViewsServicePublic; + embeddable: EmbeddableSetup; + expressions: ExpressionsSetup; + globalSearch?: GlobalSearchPluginSetup; + home?: HomePublicPluginSetup; + observabilityAIAssistant?: ObservabilityAIAssistantPublicSetup; + share?: SharePluginSetup; + uiActions: UiActionsSetup; + urlForwarding: UrlForwardingSetup; +} + +/** + * @internal + */ +export interface DiscoverStartPlugins { + aiops?: AiopsPluginStart; + charts: ChartsPluginStart; + contentManagement: ContentManagementPublicStart; + data: DataPublicPluginStart; + dataViewEditor: DataViewEditorStart; + dataViewFieldEditor: IndexPatternFieldEditorStart; + dataViews: DataViewsServicePublic; + dataVisualizer?: DataVisualizerPluginStart; + embeddable: EmbeddableStart; + expressions: ExpressionsStart; + fieldFormats: FieldFormatsStart; + inspector: InspectorPublicPluginStart; + lens: LensPublicStart; + navigation: NavigationStart; + noDataPage?: NoDataPagePluginStart; + observabilityAIAssistant?: ObservabilityAIAssistantPublicStart; + savedObjectsManagement: SavedObjectsManagementPluginStart; + savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart; + savedSearch: SavedSearchPublicPluginStart; + share?: SharePluginStart; + spaces?: SpacesPluginStart; + triggersActionsUi: TriggersAndActionsUIPublicPluginStart; + uiActions: UiActionsStart; + unifiedDocViewer: UnifiedDocViewerStart; + unifiedSearch: UnifiedSearchPublicPluginStart; + urlForwarding: UrlForwardingStart; + usageCollection?: UsageCollectionSetup; +} diff --git a/src/plugins/discover/public/utils/initialize_kbn_url_tracking.test.ts b/src/plugins/discover/public/utils/initialize_kbn_url_tracking.test.ts index e4a9a3edf6f64..999c75238739a 100644 --- a/src/plugins/discover/public/utils/initialize_kbn_url_tracking.test.ts +++ b/src/plugins/discover/public/utils/initialize_kbn_url_tracking.test.ts @@ -8,7 +8,7 @@ import { AppUpdater } from '@kbn/core/public'; import { BehaviorSubject, Observable } from 'rxjs'; import { coreMock, scopedHistoryMock } from '@kbn/core/public/mocks'; -import { DiscoverSetupPlugins } from '../plugin'; +import { DiscoverSetupPlugins } from '../types'; import { initializeKbnUrlTracking } from './initialize_kbn_url_tracking'; describe('initializeKbnUrlTracking', () => { diff --git a/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts b/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts index 7ae8ac6d132ef..8a4ed741acecf 100644 --- a/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts +++ b/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts @@ -12,7 +12,7 @@ import { createKbnUrlTracker } from '@kbn/kibana-utils-plugin/public'; import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common'; import { isFilterPinned } from '@kbn/es-query'; import { SEARCH_SESSION_ID_QUERY_PARAM } from '../constants'; -import type { DiscoverSetupPlugins } from '../plugin'; +import type { DiscoverSetupPlugins } from '../types'; /** * It creates the kbn url tracker for Discover to listens to history changes and optionally to global state diff --git a/x-pack/plugins/observability_solution/apm/public/plugin.ts b/x-pack/plugins/observability_solution/apm/public/plugin.ts index 2f2f630cd43e7..82c05479c0520 100644 --- a/x-pack/plugins/observability_solution/apm/public/plugin.ts +++ b/x-pack/plugins/observability_solution/apm/public/plugin.ts @@ -20,7 +20,7 @@ import { } from '@kbn/core/public'; import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import { DiscoverSetup, DiscoverStart } from '@kbn/discover-plugin/public/plugin'; +import { DiscoverSetup, DiscoverStart } from '@kbn/discover-plugin/public'; import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { ExploratoryViewPublicSetup } from '@kbn/exploratory-view-plugin/public'; import type { FeaturesPluginSetup } from '@kbn/features-plugin/public'; diff --git a/x-pack/plugins/observability_solution/logs_explorer/common/constants.ts b/x-pack/plugins/observability_solution/logs_explorer/common/constants.ts index ae8eff46fe7e2..54ef1b50c587c 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/common/constants.ts +++ b/x-pack/plugins/observability_solution/logs_explorer/common/constants.ts @@ -59,6 +59,3 @@ export const FILTER_OUT_FIELDS_PREFIXES_FOR_CONTENT = [ 'log.', 'service.', ]; - -export const DEFAULT_ALLOWED_DATA_VIEWS = ['logs', 'auditbeat', 'filebeat', 'winlogbeat']; -export const DEFAULT_ALLOWED_LOGS_DATA_VIEWS = ['logs', 'auditbeat', 'filebeat', 'winlogbeat']; diff --git a/x-pack/plugins/observability_solution/logs_explorer/common/data_views/models/data_view_descriptor.ts b/x-pack/plugins/observability_solution/logs_explorer/common/data_views/models/data_view_descriptor.ts index 5b36b8e8bbe8b..b5fe3d1f58c0f 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/common/data_views/models/data_view_descriptor.ts +++ b/x-pack/plugins/observability_solution/logs_explorer/common/data_views/models/data_view_descriptor.ts @@ -5,15 +5,13 @@ * 2.0. */ -import { DEFAULT_ALLOWED_LOGS_DATA_VIEWS } from '../../constants'; +import { createRegExpPatternFrom, testPatternAgainstAllowedList } from '@kbn/data-view-utils'; +import { DEFAULT_ALLOWED_LOGS_BASE_PATTERNS } from '@kbn/discover-utils'; import { DataViewSpecWithId } from '../../data_source_selection'; import { DataViewDescriptorType } from '../types'; -import { buildIndexPatternRegExp } from '../utils'; -type AllowedList = Array; - -const LOGS_ALLOWED_LIST: AllowedList = [ - buildIndexPatternRegExp(DEFAULT_ALLOWED_LOGS_DATA_VIEWS), +const LOGS_ALLOWED_LIST = [ + createRegExpPatternFrom(DEFAULT_ALLOWED_LOGS_BASE_PATTERNS), // Add more strings or regex patterns as needed ]; @@ -60,7 +58,9 @@ export class DataViewDescriptor { } testAgainstAllowedList(allowedList: string[]) { - return this.title ? isAllowed(this.title, [buildIndexPatternRegExp(allowedList)]) : false; + return this.title + ? testPatternAgainstAllowedList([createRegExpPatternFrom(allowedList)])(this.title) + : false; } public static create({ id, namespaces, title, type, name }: DataViewDescriptorFactoryParams) { @@ -79,7 +79,7 @@ export class DataViewDescriptor { } static #extractDataType(title: string): DataViewDescriptorType['dataType'] { - if (isAllowed(title, LOGS_ALLOWED_LIST)) { + if (testPatternAgainstAllowedList(LOGS_ALLOWED_LIST)(title)) { return 'logs'; } @@ -98,17 +98,3 @@ export class DataViewDescriptor { return this.dataType === 'unresolved'; } } - -function isAllowed(value: string, allowList: AllowedList) { - for (const allowedItem of allowList) { - if (typeof allowedItem === 'string') { - return value === allowedItem; - } - if (allowedItem instanceof RegExp) { - return allowedItem.test(value); - } - } - - // If no match is found in the allowList, return false - return false; -} diff --git a/x-pack/plugins/observability_solution/logs_explorer/common/ui_settings.ts b/x-pack/plugins/observability_solution/logs_explorer/common/ui_settings.ts index bbd3543d0dc69..65983c3993488 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/common/ui_settings.ts +++ b/x-pack/plugins/observability_solution/logs_explorer/common/ui_settings.ts @@ -7,9 +7,9 @@ import { schema } from '@kbn/config-schema'; import { UiSettingsParams } from '@kbn/core-ui-settings-common'; +import { DEFAULT_ALLOWED_LOGS_BASE_PATTERNS } from '@kbn/discover-utils'; import { i18n } from '@kbn/i18n'; import { OBSERVABILITY_LOGS_EXPLORER_ALLOWED_DATA_VIEWS_ID } from '@kbn/management-settings-ids'; -import { DEFAULT_ALLOWED_DATA_VIEWS } from './constants'; /** * uiSettings definitions for Logs Explorer. @@ -20,7 +20,7 @@ export const uiSettings: Record = { name: i18n.translate('xpack.logsExplorer.allowedDataViews', { defaultMessage: 'Logs Explorer allowed data views', }), - value: DEFAULT_ALLOWED_DATA_VIEWS, + value: DEFAULT_ALLOWED_LOGS_BASE_PATTERNS, description: i18n.translate('xpack.logsExplorer.allowedDataViewsDescription', { defaultMessage: 'A list of base patterns to match and explore data views in Logs Explorer. Remote clusters will be automatically matched for the provided base patterns.', diff --git a/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json b/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json index b30605fd567fd..b3f8c978a67b4 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json +++ b/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json @@ -44,6 +44,7 @@ "@kbn/unified-search-plugin", "@kbn/xstate-utils", "@kbn/esql-utils", + "@kbn/data-view-utils", ], "exclude": [ "target/**/*" diff --git a/x-pack/test/functional/apps/observability_logs_explorer/data_source_selector.ts b/x-pack/test/functional/apps/observability_logs_explorer/data_source_selector.ts index 100d547cdb07d..d4774b1ef6601 100644 --- a/x-pack/test/functional/apps/observability_logs_explorer/data_source_selector.ts +++ b/x-pack/test/functional/apps/observability_logs_explorer/data_source_selector.ts @@ -654,7 +654,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { PageObjects.observabilityLogsExplorer.getPanelEntries(menu) ); - expect(menuEntries.length).to.be(1); + expect(menuEntries.length).to.be(2); expect(await menuEntries[0].getVisibleText()).to.be(sortedExpectedDataViews[0]); }); From 014678003c30836faef3eb5e7222b1c0560d8c24 Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Tue, 18 Jun 2024 13:04:52 +0200 Subject: [PATCH 042/127] =?UTF-8?q?Upgrade=20@grpc/grpc-js@1.6.8=E2=86=921?= =?UTF-8?q?.8.22=20(#186067)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Upgrades the `@grpc/grpc-js` dependency from v1.6.8 to v1.8.22 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e8d694bb323e8..eaae0b675e62e 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,7 @@ "@formatjs/intl-pluralrules": "^5.2.12", "@formatjs/intl-relativetimeformat": "^11.2.12", "@formatjs/intl-utils": "^3.8.4", - "@grpc/grpc-js": "^1.6.8", + "@grpc/grpc-js": "^1.8.22", "@hapi/accept": "^5.0.2", "@hapi/boom": "^9.1.4", "@hapi/cookie": "^11.0.2", diff --git a/yarn.lock b/yarn.lock index abf9faf49c8ae..463d1d469c7b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2490,10 +2490,10 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@grpc/grpc-js@^1.6.8", "@grpc/grpc-js@^1.7.1": - version "1.8.17" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.17.tgz#a3a2f826fc033eae7d2f5ee41e0ab39cee948838" - integrity sha512-DGuSbtMFbaRsyffMf+VEkVu8HkSXEUfO3UyGJNtqxW9ABdtTIA+2UXAJpwbJS+xfQxuwqLUeELmL6FuZkOqPxw== +"@grpc/grpc-js@^1.7.1", "@grpc/grpc-js@^1.8.22": + version "1.8.22" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.22.tgz#847930c9af46e14df05b57fc12325db140ceff1d" + integrity sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA== dependencies: "@grpc/proto-loader" "^0.7.0" "@types/node" ">=12.12.47" From 7528264531a806c6edda08c7a37c85ddbb05213f Mon Sep 17 00:00:00 2001 From: Bena Kansara <69037875+benakansara@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:14:37 +0200 Subject: [PATCH 043/127] [Observability] [Alert detail pages] Make common alert summary fields consistent for all pages with clickable source (#185933) Closes https://github.com/elastic/kibana/issues/183624 Closes https://github.com/elastic/kibana/issues/181692 Makes common alert summary fields consistent for all alert detail pages, with clickable links for source fields. Common alert summary fields: - Source - Tags - Rule Any additional fields specified in `AlertDetailsAppSection` would appear after these common fields. To make it consistent, I needed to do following small adjustments: - Changed "Source SLO" to "SLO" in burn rate alert - Changed "SLO Instance" to "Source" in burn rate alert - Moved "View related logs" to its separate label in custom threshold alert Additionally, following changes are made. - Added `kibana.alert.group` in Log threshold alert and SLO burn rate alert. - The "Affected source/entity" column in alert flyout matches the "Source" in alert details page. Before | After :---: | :---: Metric threshold alert Screenshot 2024-06-12 at
12 16 41 | Metric threshold alert Screenshot 2024-06-12 at
11 12 16 APM latency threshold alert Screenshot 2024-06-12
at 12 00 23 | APM latency threshold alert Screenshot
2024-06-12 at 11 11 23 Log threshold alert Screenshot 2024-06-12 at 12
17 42 | Log threshold alert Screenshot 2024-06-12 at 11
07 07 SLO burn rate alert Screenshot 2024-06-12 at 12
02 24 | SLO burn rate alert Screenshot 2024-06-12 at 11
12 56 Custom threshold alert Screenshot 2024-06-12 at
12 03 07 | Custom threshold alert Screenshot 2024-06-12 at
11 09 03 The "Affected source/entity" column in alert flyout matches the "Source" in alert details page. Before | After :---: | :---: Log threshold alert Screenshot 2024-06-12 at 12 11
28 | Log threshold alert Screenshot 2024-06-12 at 11
14 20 SLO burn rate alert Screenshot 2024-06-12 at 12 08
26 | SLO burn rate alert Screenshot 2024-06-12 at 11
14 44 Added `kibana.alert.group` in Log threshold alert and SLO burn rate alert. Log threshold alert Screenshot 2024-06-12 at 11 16 50 SLO burn rate alert Screenshot 2024-06-12 at 11 17 11 --- .../alert_details_app_section/index.tsx | 31 ------- .../common => common/alerting}/types.ts | 0 .../alert_details_app_section/index.tsx | 36 +------- .../alert_details_app_section/types.ts | 5 -- .../alert_details_app_section.test.tsx | 38 --------- .../components/alert_details_app_section.tsx | 54 +----------- .../metric_threshold/components/groups.tsx | 24 ------ .../infra/server/lib/alerting/common/utils.ts | 2 +- .../log_threshold/log_threshold_executor.ts | 18 +++- .../metric_threshold_executor.test.ts | 2 +- .../metric_threshold_executor.ts | 2 +- .../get_view_in_app_url.ts | 3 +- .../helpers/get_group.ts | 2 +- .../common/custom_threshold_rule/types.ts | 15 ---- .../observability/common/typings.ts | 13 +++ .../alert_overview/alert_overview.tsx | 4 +- .../alert_overview/overview_columns.tsx | 4 +- .../get_alert_source_links.test.ts | 0 .../alert_sources}/get_alert_source_links.ts | 4 +- .../alert_sources}/get_apm_app_url.ts | 0 .../helpers => alert_sources}/get_sources.ts | 13 +-- .../groups.tsx | 13 ++- .../alert_details_app_section.test.tsx | 67 +++------------ .../alert_details_app_section.tsx | 75 ++++------------- .../helpers/log_rate_analysis_query.ts | 6 +- .../alert_details_app_section/tags.tsx | 49 ----------- .../public}/components/tags.tsx | 4 +- .../pages/alert_details/alert_details.tsx | 3 +- .../components/alert_summary.test.tsx | 49 ++++++++++- .../components/alert_summary.tsx | 83 +++++++++++++++++-- .../components/header_actions.test.tsx | 30 +++---- .../public/pages/alert_details/mock/alert.ts | 13 ++- .../mock/alert_summary_fields.ts | 11 +-- .../custom_threshold_executor.ts | 2 +- .../lib/rules/custom_threshold/types.ts | 2 +- .../lib/rules/custom_threshold/utils.ts | 2 +- .../alert_details_app_section.tsx | 28 +------ .../lib/rules/slo_burn_rate/executor.test.ts | 48 +++++++++-- .../lib/rules/slo_burn_rate/executor.ts | 18 +++- .../server/lib/rules/slo_burn_rate/types.ts | 5 ++ .../translations/translations/fr-FR.json | 8 -- .../translations/translations/ja-JP.json | 8 -- .../translations/translations/zh-CN.json | 8 -- 43 files changed, 310 insertions(+), 492 deletions(-) rename x-pack/plugins/observability_solution/infra/{server/lib/alerting/common => common/alerting}/types.ts (100%) delete mode 100644 x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/groups.tsx rename x-pack/plugins/observability_solution/observability/{common/custom_threshold_rule/helpers => public/components/alert_sources}/get_alert_source_links.test.ts (100%) rename x-pack/plugins/observability_solution/observability/{common/custom_threshold_rule/helpers => public/components/alert_sources}/get_alert_source_links.ts (96%) rename x-pack/plugins/observability_solution/observability/{common/custom_threshold_rule => public/components/alert_sources}/get_apm_app_url.ts (100%) rename x-pack/plugins/observability_solution/observability/public/components/{alert_overview/helpers => alert_sources}/get_sources.ts (75%) rename x-pack/plugins/observability_solution/observability/public/components/{custom_threshold/components/alert_details_app_section => alert_sources}/groups.tsx (76%) delete mode 100644 x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/tags.tsx rename x-pack/plugins/observability_solution/{infra/public/alerting/metric_threshold => observability/public}/components/tags.tsx (89%) diff --git a/x-pack/plugins/observability_solution/apm/public/components/alerting/ui_components/alert_details_app_section/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/alerting/ui_components/alert_details_app_section/index.tsx index 7bea5746e461f..b9a7f4e8d8254 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/alerting/ui_components/alert_details_app_section/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/alerting/ui_components/alert_details_app_section/index.tsx @@ -74,37 +74,6 @@ export function AlertDetailsAppSection({ ), value: formatAlertEvaluationValue(alertRuleTypeId, alertEvaluationThreshold), }, - { - label: ( - - ), - value: environment, - }, - { - label: ( - - ), - value: serviceName, - }, - ...(transactionName - ? [ - { - label: ( - - ), - value: transactionName, - }, - ] - : []), ]; setAlertSummaryFields(alertSummaryFields); }, [ diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/common/types.ts b/x-pack/plugins/observability_solution/infra/common/alerting/types.ts similarity index 100% rename from x-pack/plugins/observability_solution/infra/server/lib/alerting/common/types.ts rename to x-pack/plugins/observability_solution/infra/common/alerting/types.ts diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index ae0021adb2e01..36e2e91af9db0 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { useEffect } from 'react'; +import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { LEGACY_LIGHT_THEME } from '@elastic/charts'; import { EuiPanel } from '@elastic/eui'; @@ -37,16 +37,11 @@ import { useLicense } from '../../../../hooks/use_license'; const formatThreshold = (threshold: number) => String(threshold); -const AlertDetailsAppSection = ({ - rule, - alert, - setAlertSummaryFields, -}: AlertDetailsAppSectionProps) => { +const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => { const { logsShared } = useKibanaContextForPlugin().services; const theme = useTheme(); const timeRange = getPaddedAlertTimeRange(alert.fields[ALERT_START]!, alert.fields[ALERT_END]); const alertEnd = alert.fields[ALERT_END] ? moment(alert.fields[ALERT_END]).valueOf() : undefined; - const alertContext = alert.fields[ALERT_CONTEXT]; const interval = `${rule.params.timeSize}${rule.params.timeUnit}`; const thresholdFill = convertComparatorToFill(rule.params.count.comparator); const filter = rule.params.groupBy @@ -71,33 +66,6 @@ const AlertDetailsAppSection = ({ const { hasAtLeast } = useLicense(); const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - useEffect(() => { - /** - * The `CriterionPreview` chart shows all the series/data stacked when there is a GroupBy in the rule parameters. - * e.g., `host.name`, the chart will show stacks of data by hostname. - * We only need the chart to show the series that is related to the selected alert. - * The chart series are built based on the GroupBy in the rule params - * Each series have an id which is the just a joining of fields value of the GroupBy `getChartGroupNames` - * We filter down the series using this group name - */ - const alertFieldsFromGroupBy = - rule.params.groupBy?.reduce( - (selectedFields: Record, field) => ({ - ...selectedFields, - ...{ - [field]: get(alertContext, ['groupByKeys', ...field.split('.')], null), - }, - }), - {} - ) || {}; - - const alertSummaryFields = Object.entries(alertFieldsFromGroupBy).map(([label, value]) => ({ - label, - value, - })); - setAlertSummaryFields(alertSummaryFields); - }, [alertContext, rule.params.groupBy, setAlertSummaryFields]); - const getLogRatioChart = () => { if (isRatioRule(rule.params.criteria)) { const numeratorKql = rule.params.criteria[0] diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/types.ts b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/types.ts index ee89bc3baea63..c76778aa81251 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/types.ts +++ b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/alert_details_app_section/types.ts @@ -14,8 +14,3 @@ export interface AlertDetailsAppSectionProps { alert: TopAlert>; setAlertSummaryFields: React.Dispatch>; } - -export interface Group { - field: string; - value: string; -} diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.test.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.test.tsx index f7827fcbcadbb..eaf077684cf4d 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.test.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.test.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; -import { EuiLink } from '@elastic/eui'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { coreMock as mockCoreMock } from '@kbn/core/public/mocks'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; @@ -18,8 +17,6 @@ import { } from '../mocks/metric_threshold_rule'; import { AlertDetailsAppSection } from './alert_details_app_section'; import { ExpressionChart } from './expression_chart'; -import { Groups } from './groups'; -import { Tags } from './tags'; const mockedChartStartContract = chartPluginMock.createStartContract(); @@ -51,7 +48,6 @@ jest.mock('../../../hooks/use_kibana', () => ({ describe('AlertDetailsAppSection', () => { const queryClient = new QueryClient(); const mockedSetAlertSummaryFields = jest.fn(); - const ruleLink = 'ruleLink'; const renderComponent = () => { return render( @@ -59,7 +55,6 @@ describe('AlertDetailsAppSection', () => { @@ -78,39 +73,6 @@ describe('AlertDetailsAppSection', () => { expect(result.getByTestId('threshold-2000-2500')).toBeTruthy(); }); - it('should render alert summary fields', async () => { - renderComponent(); - - expect(mockedSetAlertSummaryFields).toBeCalledTimes(1); - expect(mockedSetAlertSummaryFields).toBeCalledWith([ - { - label: 'Source', - value: ( - - ), - }, - { - label: 'Tags', - value: , - }, - { - label: 'Rule', - value: ( - - Monitoring hosts - - ), - }, - ]); - }); - it('should render annotations', async () => { const mockedExpressionChart = jest.fn(() =>
); (ExpressionChart as jest.Mock).mockImplementation(mockedExpressionChart); diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.tsx index 6a9e4999714bc..bee0035f210c1 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/alert_details_app_section.tsx @@ -7,25 +7,18 @@ import { i18n } from '@kbn/i18n'; import { convertToBuiltInComparators } from '@kbn/observability-plugin/common'; -import React, { useEffect } from 'react'; +import React from 'react'; import moment from 'moment'; import { EuiFlexGroup, EuiFlexItem, - EuiLink, EuiPanel, EuiSpacer, EuiTitle, useEuiTheme, } from '@elastic/eui'; import { AlertSummaryField, TopAlert } from '@kbn/observability-plugin/public'; -import { - ALERT_END, - ALERT_START, - ALERT_EVALUATION_VALUES, - ALERT_GROUP, - TAGS, -} from '@kbn/rule-data-utils'; +import { ALERT_END, ALERT_START, ALERT_EVALUATION_VALUES, ALERT_GROUP } from '@kbn/rule-data-utils'; import { Rule } from '@kbn/alerting-plugin/common'; import { AlertAnnotation, AlertActiveTimeRangeAnnotation } from '@kbn/observability-alert-details'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; @@ -37,8 +30,6 @@ import { MetricsExplorerChartType } from '../../../pages/metrics/metrics_explore import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { MetricThresholdRuleTypeParams } from '..'; import { ExpressionChart } from './expression_chart'; -import { Groups } from './groups'; -import { Tags } from './tags'; // TODO Use a generic props for app sections https://github.com/elastic/kibana/issues/152690 export type MetricThresholdRule = Rule< @@ -67,21 +58,13 @@ const ALERT_TIME_RANGE_ANNOTATION_ID = 'alert_time_range_annotation'; interface AppSectionProps { alert: MetricThresholdAlert; rule: MetricThresholdRule; - ruleLink: string; setAlertSummaryFields: React.Dispatch>; } -export function AlertDetailsAppSection({ - alert, - rule, - ruleLink, - setAlertSummaryFields, -}: AppSectionProps) { +export function AlertDetailsAppSection({ alert, rule }: AppSectionProps) { const { uiSettings, charts } = useKibanaContextForPlugin().services; const { euiTheme } = useEuiTheme(); const groupInstance = alert.fields[ALERT_GROUP]?.map((group: Group) => group.value); - const groups = alert.fields[ALERT_GROUP]; - const tags = alert.fields[TAGS]; const chartProps = { baseTheme: charts.theme.useChartsBaseTheme(), @@ -103,37 +86,6 @@ export function AlertDetailsAppSection({ key={ALERT_TIME_RANGE_ANNOTATION_ID} />, ]; - useEffect(() => { - const alertSummaryFields = []; - if (groups) { - alertSummaryFields.push({ - label: i18n.translate('xpack.infra.metrics.alertDetailsAppSection.summaryField.source', { - defaultMessage: 'Source', - }), - value: , - }); - } - if (tags && tags.length > 0) { - alertSummaryFields.push({ - label: i18n.translate('xpack.infra.metrics.alertDetailsAppSection.summaryField.tags', { - defaultMessage: 'Tags', - }), - value: , - }); - } - alertSummaryFields.push({ - label: i18n.translate('xpack.infra.metrics.alertDetailsAppSection.summaryField.rule', { - defaultMessage: 'Rule', - }), - value: ( - - {rule.name} - - ), - }); - - setAlertSummaryFields(alertSummaryFields); - }, [groups, tags, rule, ruleLink, setAlertSummaryFields]); return !!rule.params.criteria ? ( diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/groups.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/groups.tsx deleted file mode 100644 index c68fa2a391448..0000000000000 --- a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/groups.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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -export function Groups({ groups }: { groups: Array<{ field: string; value: string }> }) { - return ( - <> - {groups && - groups.map((group) => { - return ( - - {group.field}: {group.value} -
-
- ); - })} - - ); -} diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/common/utils.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/common/utils.ts index 9c506d215355a..edfb50df0a788 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/common/utils.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/common/utils.ts @@ -28,7 +28,7 @@ import { AlertExecutionDetails, InventoryMetricConditions, } from '../../../../common/alerting/metrics/types'; -import { Group } from './types'; +import { Group } from '../../../../common/alerting/types'; const ALERT_CONTEXT_CONTAINER = 'container'; const ALERT_CONTEXT_ORCHESTRATOR = 'orchestrator'; diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index 01eed0023dda8..68eea51669e87 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -12,6 +12,7 @@ import { ALERT_CONTEXT, ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, + ALERT_GROUP, ALERT_REASON, } from '@kbn/rule-data-utils'; import { ElasticsearchClient, IBasePath } from '@kbn/core/server'; @@ -76,15 +77,20 @@ import { LogThresholdRuleTypeParams, positiveComparators, } from '../../../../common/alerting/logs/log_threshold/query_helpers'; +import { Group } from '../../../../common/alerting/types'; export type LogThresholdActionGroups = ActionGroupIdsOf; export type LogThresholdRuleTypeState = RuleTypeState; // no specific state used export type LogThresholdAlertState = AlertState; // no specific state used export type LogThresholdAlertContext = AlertContext; // no specific instance context used -export type LogThresholdAlert = Omit & { +export type LogThresholdAlert = Omit< + ObservabilityLogsAlert, + 'kibana.alert.evaluation.values' | 'kibana.alert.group' +> & { // Defining a custom type for this because the schema generation script doesn't allow explicit null values 'kibana.alert.evaluation.values'?: Array; + [ALERT_GROUP]?: Group[]; }; export type LogThresholdAlertReporter = ( @@ -169,11 +175,21 @@ export const createLogThresholdExecutor = alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, uuid), }; + const instances = alertInstanceId.split(','); + const groups = + alertInstanceId !== '*' + ? params.groupBy?.reduce((resultGroups, groupByItem, index) => { + resultGroups.push({ field: groupByItem, value: instances[index].trim() }); + return resultGroups; + }, []) + : undefined; + const payload = { [ALERT_EVALUATION_THRESHOLD]: threshold, [ALERT_EVALUATION_VALUE]: value, [ALERT_REASON]: reason, [ALERT_CONTEXT]: alertContext, + [ALERT_GROUP]: groups, ...flattenAdditionalContext(rootLevelContext), }; diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 9cc5712ce09b6..d95a24478a6ff 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -30,7 +30,7 @@ import { ALERT_REASON, ALERT_GROUP, } from '@kbn/rule-data-utils'; -import { Group } from '../common/types'; +import { Group } from '../../../../common/alerting/types'; jest.mock('./lib/evaluate_rule', () => ({ evaluateRule: jest.fn() })); diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index 49129e2058cc1..f05c98d6cc222 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -48,11 +48,11 @@ import { getFormattedGroupBy, } from '../common/utils'; import { getEvaluationValues, getThresholds } from '../common/get_values'; -import { Group } from '../common/types'; import { EvaluatedRuleParams, evaluateRule, Evaluation } from './lib/evaluate_rule'; import { MissingGroupsRecord } from './lib/check_missing_group'; import { convertStringsToMissingGroupsRecord } from './lib/convert_strings_to_missing_groups_record'; +import { Group } from '../../../../common/alerting/types'; export type MetricThresholdAlert = Omit< ObservabilityMetricsAlert, diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/get_view_in_app_url.ts b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/get_view_in_app_url.ts index 9715b8b5f9c86..5411eff43bc3d 100644 --- a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/get_view_in_app_url.ts +++ b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/get_view_in_app_url.ts @@ -10,8 +10,9 @@ import type { TimeRange } from '@kbn/es-query'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; import type { LocatorPublic } from '@kbn/share-plugin/common'; import { getGroupFilters } from './helpers/get_group'; -import { Group, SearchConfigurationWithExtractedReferenceType } from './types'; +import { SearchConfigurationWithExtractedReferenceType } from './types'; import type { CustomThresholdExpressionMetric } from './types'; +import { Group } from '../typings'; export interface GetViewInAppUrlArgs { searchConfiguration?: SearchConfigurationWithExtractedReferenceType; diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts index 3194fc4e14b2d..67437421e4bad 100644 --- a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts +++ b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts @@ -7,7 +7,7 @@ import { Filter } from '@kbn/es-query'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { Group } from '../types'; +import { Group } from '../../typings'; /* * groupFieldName diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts index 0e4a0e7167069..c2a616682cfdb 100644 --- a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts +++ b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts @@ -106,16 +106,6 @@ export enum InfraFormatterType { percent = 'percent', } -export interface Group { - field: string; - value: string; -} - -export interface TimeRange { - from?: string; - to?: string; -} - export interface SearchConfigurationType { index: SerializedSearchSourceFields; query: { @@ -135,11 +125,6 @@ export interface SearchConfigurationWithExtractedReferenceType { filter?: Filter[]; } -// Custom threshold alert types - -// Alert fields['kibana.alert.group] type -export type GroupBy = Group[]; - /* * Utils * diff --git a/x-pack/plugins/observability_solution/observability/common/typings.ts b/x-pack/plugins/observability_solution/observability/common/typings.ts index dfddf89992c19..bfdcd6d5209dc 100644 --- a/x-pack/plugins/observability_solution/observability/common/typings.ts +++ b/x-pack/plugins/observability_solution/observability/common/typings.ts @@ -41,3 +41,16 @@ export interface AlertStatusFilter { query: string; label: string; } + +export interface Group { + field: string; + value: string; +} + +export interface TimeRange { + from?: string; + to?: string; +} + +// Alert fields['kibana.alert.group] type +export type GroupBy = Group[]; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_overview/alert_overview.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_overview/alert_overview.tsx index 95e043dd3da1c..57a34d7fdf1f9 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_overview/alert_overview.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_overview/alert_overview.tsx @@ -34,7 +34,6 @@ import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-tim import { get } from 'lodash'; import { paths } from '../../../common/locators/paths'; -import { TimeRange } from '../../../common/custom_threshold_rule/types'; import { TopAlert } from '../../typings/alerts'; import { useFetchBulkCases } from '../../hooks/use_fetch_bulk_cases'; import { useCaseViewNavigation } from '../../hooks/use_case_view_navigation'; @@ -44,8 +43,9 @@ import { mapRuleParamsWithFlyout, } from './helpers/map_rules_params_with_flyout'; import { ColumnIDs, overviewColumns } from './overview_columns'; -import { getSources } from './helpers/get_sources'; +import { getSources } from '../alert_sources/get_sources'; import { RULE_DETAILS_PAGE_ID } from '../../pages/rule_details/constants'; +import { TimeRange } from '../../../common/typings'; export const AlertOverview = memo( ({ diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_overview/overview_columns.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_overview/overview_columns.tsx index a1581333294ea..d2c3eb58854ee 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_overview/overview_columns.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_overview/overview_columns.tsx @@ -15,11 +15,11 @@ import React from 'react'; import { Tooltip as CaseTooltip } from '@kbn/cases-components'; import { COMPARATORS } from '@kbn/alerting-comparators'; import { LEGACY_COMPARATORS } from '../../../common/utils/convert_legacy_outside_comparator'; -import type { Group } from '../../../common/custom_threshold_rule/types'; import { NavigateToCaseView } from '../../hooks/use_case_view_navigation'; -import { Groups } from '../custom_threshold/components/alert_details_app_section/groups'; import { formatCase } from './helpers/format_cases'; import { FlyoutThresholdData } from './helpers/map_rules_params_with_flyout'; +import { Groups } from '../alert_sources/groups'; +import type { Group } from '../../../common/typings'; interface AlertOverviewField { id: string; diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_alert_source_links.test.ts b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_alert_source_links.test.ts similarity index 100% rename from x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_alert_source_links.test.ts rename to x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_alert_source_links.test.ts diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_alert_source_links.ts b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_alert_source_links.ts similarity index 96% rename from x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_alert_source_links.ts rename to x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_alert_source_links.ts index 0595d7554fb0b..ff1d39d85b1d4 100644 --- a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_alert_source_links.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_alert_source_links.ts @@ -13,8 +13,8 @@ import { } from '@kbn/observability-shared-plugin/common'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { SerializableRecord } from '@kbn/utility-types'; -import { getApmAppLocator } from '../get_apm_app_url'; -import { Group, TimeRange } from '../types'; +import { getApmAppLocator } from './get_apm_app_url'; +import { Group, TimeRange } from '../../../common/typings'; const HOST_NAME = 'host.name'; const CONTAINER_ID = 'container.id'; diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/get_apm_app_url.ts b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_apm_app_url.ts similarity index 100% rename from x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/get_apm_app_url.ts rename to x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_apm_app_url.ts diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_overview/helpers/get_sources.ts b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_sources.ts similarity index 75% rename from x-pack/plugins/observability_solution/observability/public/components/alert_overview/helpers/get_sources.ts rename to x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_sources.ts index cfc64d9d414aa..3832e744a31e6 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_overview/helpers/get_sources.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/get_sources.ts @@ -5,18 +5,19 @@ * 2.0. */ -import { ALERT_GROUP_FIELD, ALERT_GROUP_VALUE } from '@kbn/rule-data-utils'; -import { - apmSources, - infraSources, -} from '../../../../common/custom_threshold_rule/helpers/get_alert_source_links'; -import { TopAlert } from '../../..'; +import { ALERT_GROUP_FIELD, ALERT_GROUP_VALUE, ALERT_GROUP } from '@kbn/rule-data-utils'; +import { TopAlert } from '../../typings/alerts'; +import { apmSources, infraSources } from './get_alert_source_links'; interface AlertFields { [key: string]: any; } export const getSources = (alert: TopAlert) => { + // when `kibana.alert.group` is not flattened (for alert detail pages) + if (alert.fields[ALERT_GROUP]) return alert.fields[ALERT_GROUP]; + + // when `kibana.alert.group` is flattened (for alert flyout) const groupsFromGroupFields = alert.fields[ALERT_GROUP_FIELD]?.map((field, index) => { const values = alert.fields[ALERT_GROUP_VALUE]; if (values?.length && values[index]) { diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/groups.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/groups.tsx similarity index 76% rename from x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/groups.tsx rename to x-pack/plugins/observability_solution/observability/public/components/alert_sources/groups.tsx index f2644ac78b0c5..5a14f39a97811 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/groups.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_sources/groups.tsx @@ -8,10 +8,10 @@ import { EuiLink } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; import { SERVICE_NAME } from '@kbn/observability-shared-plugin/common'; -import { useKibana } from '../../../../utils/kibana_react'; -import { TimeRange, Group } from '../../../../../common/custom_threshold_rule/types'; -import { generateSourceLink } from '../../../../../common/custom_threshold_rule/helpers/get_alert_source_links'; -import { APM_APP_LOCATOR_ID } from '../../../../../common/custom_threshold_rule/get_apm_app_url'; +import { useKibana } from '../../utils/kibana_react'; +import { APM_APP_LOCATOR_ID } from './get_apm_app_url'; +import { Group, TimeRange } from '../../../common/typings'; +import { generateSourceLink } from './get_alert_source_links'; export function Groups({ groups, timeRange }: { groups: Group[]; timeRange: TimeRange }) { const { @@ -57,10 +57,7 @@ export function Groups({ groups, timeRange }: { groups: Group[]; timeRange: Time {group.field}:{' '} {sourceLinks[group.field] ? ( - + {group.value} ) : ( diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx index a30511c891e7b..35104fd199d3a 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx @@ -21,8 +21,6 @@ import { CustomThresholdAlertFields } from '../../types'; import { RuleConditionChart } from '../rule_condition_chart/rule_condition_chart'; import { CustomThresholdAlert } from '../types'; import AlertDetailsAppSection from './alert_details_app_section'; -import { Groups } from './groups'; -import { Tags } from './tags'; const mockedChartStartContract = chartPluginMock.createStartContract(); @@ -80,7 +78,6 @@ jest.mock('../../../../utils/kibana_react', () => ({ describe('AlertDetailsAppSection', () => { const queryClient = new QueryClient(); const mockedSetAlertSummaryFields = jest.fn(); - const ruleLink = 'ruleLink'; const renderComponent = ( alert: Partial = {}, @@ -92,7 +89,6 @@ describe('AlertDetailsAppSection', () => { @@ -111,65 +107,22 @@ describe('AlertDetailsAppSection', () => { expect(result.getByTestId('thresholdRule-2000-2500')).toBeTruthy(); }); - it('should render alert summary fields', async () => { + it('should render additional alert summary fields', async () => { renderComponent(); expect(mockedSetAlertSummaryFields).toBeCalledTimes(2); expect(mockedSetAlertSummaryFields).toBeCalledWith([ { - label: 'Source', + label: 'Related logs', value: ( - - - - - View related logs - - - - ), - }, - { - label: 'Tags', - value: , - }, - { - label: 'Rule', - value: ( - - Monitoring hosts - - ), - }, - ]); - }); - - it('should not render group and tag summary fields', async () => { - const alertFields = { tags: [], 'kibana.alert.group': undefined }; - renderComponent({}, alertFields); - - expect(mockedSetAlertSummaryFields).toBeCalledTimes(2); - expect(mockedSetAlertSummaryFields).toBeCalledWith([ - { - label: 'Rule', - value: ( - - Monitoring hosts - + + + View related logs + + ), }, ]); diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index c0c399914acd9..3a065d6e06f3e 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -21,13 +21,7 @@ import { } from '@elastic/eui'; import { RuleTypeParams } from '@kbn/alerting-plugin/common'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; -import { - ALERT_END, - ALERT_START, - ALERT_EVALUATION_VALUES, - ALERT_GROUP, - TAGS, -} from '@kbn/rule-data-utils'; +import { ALERT_END, ALERT_START, ALERT_EVALUATION_VALUES, ALERT_GROUP } from '@kbn/rule-data-utils'; import { DataView } from '@kbn/data-views-plugin/common'; import type { EventAnnotationConfig, @@ -46,8 +40,6 @@ import { AlertParams } from '../../types'; import { Threshold } from '../custom_threshold'; import { CustomThresholdRule, CustomThresholdAlert } from '../types'; import { LogRateAnalysis } from './log_rate_analysis'; -import { Groups } from './groups'; -import { Tags } from './tags'; import { RuleConditionChart } from '../rule_condition_chart/rule_condition_chart'; import { getViewInAppUrl } from '../../../../../common/custom_threshold_rule/get_view_in_app_url'; import { SearchConfigurationWithExtractedReferenceType } from '../../../../../common/custom_threshold_rule/types'; @@ -56,7 +48,6 @@ import { generateChartTitleAndTooltip } from './helpers/generate_chart_title_and interface AppSectionProps { alert: CustomThresholdAlert; rule: CustomThresholdRule; - ruleLink: string; setAlertSummaryFields: React.Dispatch>; } @@ -64,7 +55,6 @@ interface AppSectionProps { export default function AlertDetailsAppSection({ alert, rule, - ruleLink, setAlertSummaryFields, }: AppSectionProps) { const services = useKibana().services; @@ -89,7 +79,6 @@ export default function AlertDetailsAppSection({ const alertStart = alert.fields[ALERT_START]; const alertEnd = alert.fields[ALERT_END]; const groups = alert.fields[ALERT_GROUP]; - const tags = alert.fields[TAGS]; const chartTitleAndTooltip: Array<{ title: string; tooltip: string }> = []; @@ -145,64 +134,30 @@ export default function AlertDetailsAppSection({ useEffect(() => { const alertSummaryFields = []; - if (groups) { - alertSummaryFields.push({ - label: i18n.translate( - 'xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.source', - { - defaultMessage: 'Source', - } - ), - value: ( - <> - - - - {i18n.translate( - 'xpack.observability.alertDetailsAppSection.a.viewRelatedLogsLabel', - { - defaultMessage: 'View related logs', - } - )} - - - - ), - }); - } - if (tags && tags.length > 0) { - alertSummaryFields.push({ - label: i18n.translate( - 'xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.tags', - { - defaultMessage: 'Tags', - } - ), - value: , - }); - } + alertSummaryFields.push({ label: i18n.translate( - 'xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.rule', + 'xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.relatedLogs', { - defaultMessage: 'Rule', + defaultMessage: 'Related logs', } ), value: ( - - {rule.name} - + + + {i18n.translate('xpack.observability.alertDetailsAppSection.a.viewRelatedLogsLabel', { + defaultMessage: 'View related logs', + })} + + ), }); setAlertSummaryFields(alertSummaryFields); - }, [groups, tags, rule, ruleLink, setAlertSummaryFields, timeRange, alertEnd, viewInAppUrl]); + }, [viewInAppUrl, setAlertSummaryFields]); useEffect(() => { const initDataView = async () => { diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts index 2eb3186a46a9d..a23105f08cebf 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts @@ -10,12 +10,10 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { getGroupFilters } from '../../../../../../common/custom_threshold_rule/helpers/get_group'; import { Aggregators } from '../../../../../../common/custom_threshold_rule/types'; import { buildEsQuery } from '../../../../../utils/build_es_query'; -import type { - CustomThresholdExpressionMetric, - Group, -} from '../../../../../../common/custom_threshold_rule/types'; +import type { CustomThresholdExpressionMetric } from '../../../../../../common/custom_threshold_rule/types'; import type { TopAlert } from '../../../../../typings/alerts'; import type { CustomThresholdRuleTypeParams } from '../../../types'; +import { Group } from '../../../../../../common/typings'; const getKuery = (metrics: CustomThresholdExpressionMetric[], filter?: string) => { let query = ''; diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/tags.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/tags.tsx deleted file mode 100644 index b04d104695de8..0000000000000 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/alert_details_app_section/tags.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; -import React, { useState } from 'react'; -import { EuiBadge, EuiPopover } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; - -export function Tags({ tags }: { tags: string[] }) { - const [isMoreTagsOpen, setIsMoreTagsOpen] = useState(false); - const onMoreTagsClick = () => setIsMoreTagsOpen((isPopoverOpen) => !isPopoverOpen); - const closePopover = () => setIsMoreTagsOpen(false); - const moreTags = tags.length > 3 && ( - - - - ); - - return ( - <> - {tags.slice(0, 3).map((tag) => ( - {tag} - ))} -
- - {tags.slice(3).map((tag) => ( - {tag} - ))} - - - ); -} diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/tags.tsx b/x-pack/plugins/observability_solution/observability/public/components/tags.tsx similarity index 89% rename from x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/tags.tsx rename to x-pack/plugins/observability_solution/observability/public/components/tags.tsx index 6d5cb11a63b67..e7059463ef7bd 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/tags.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/tags.tsx @@ -19,14 +19,14 @@ export function Tags({ tags }: { tags: string[] }) { key="more" onClick={onMoreTagsClick} onClickAriaLabel={i18n.translate( - 'xpack.infra.metrics.alertDetailsAppSection.summaryField.moreTags.ariaLabel', + 'xpack.observability.alertDetails.alertSummaryField.moreTags.ariaLabel', { defaultMessage: 'more tags badge', } )} > diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx index e2bbfe4edda9a..e17fc1666e061 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details.tsx @@ -174,7 +174,7 @@ export function AlertDetails() { isAlertDetailsEnabledPerApp(alertDetail.formatted, config) ? ( <> - + {rule && alertDetail.formatted && ( @@ -184,7 +184,6 @@ export function AlertDetails() { rule={rule} timeZone={timeZone} setAlertSummaryFields={setSummaryFields} - ruleLink={http.basePath.prepend(paths.observability.ruleDetails(rule.id))} /> ({ ...jest.requireActual('react-router-dom'), @@ -19,6 +29,21 @@ jest.mock('react-router-dom', () => ({ jest.mock('../../../utils/kibana_react'); +const useKibanaMock = useKibana as jest.Mock; + +const mockKibana = () => { + useKibanaMock.mockReturnValue({ + services: { + ...kibanaStartMock.startContract().services, + http: { + basePath: { + prepend: jest.fn(), + }, + }, + }, + }); +}; + describe('Alert summary', () => { jest .spyOn(useUiSettingHook, 'useUiSetting') @@ -26,14 +51,30 @@ describe('Alert summary', () => { beforeEach(() => { jest.clearAllMocks(); + mockKibana(); }); it('should show alert data', async () => { - const alertSummary = render(); + const alertSummary = render( + + ); + + const groups = alertWithGroupsAndTags.fields[ALERT_GROUP] as Group[]; + expect(alertSummary.queryByText('Source')).toBeInTheDocument(); + expect(alertSummary.queryByText(groups[0].field, { exact: false })).toBeInTheDocument(); + expect(alertSummary.queryByText(groups[0].value)).toBeInTheDocument(); + expect(alertSummary.queryByText(groups[1].field, { exact: false })).toBeInTheDocument(); + expect(alertSummary.queryByText(groups[1].value)).toBeInTheDocument(); + expect(alertSummary.queryByText('Tags')).toBeInTheDocument(); + expect(alertSummary.queryByText(alertWithGroupsAndTags.fields[TAGS]![0])).toBeInTheDocument(); + expect(alertSummary.queryByText('Rule')).toBeInTheDocument(); + expect( + alertSummary.queryByText(alertWithGroupsAndTags.fields[ALERT_RULE_NAME]) + ).toBeInTheDocument(); expect(alertSummary.queryByText('Actual value')).toBeInTheDocument(); - expect(alertSummary.queryByText(alertWithTags.fields['kibana.alert.evaluation.value']!)); + expect(alertSummary.queryByText(alertWithGroupsAndTags.fields[ALERT_EVALUATION_VALUE]!)); expect(alertSummary.queryByText('Expected value')).toBeInTheDocument(); - expect(alertSummary.queryByText(alertWithTags.fields['kibana.alert.evaluation.threshold']!)); + expect(alertSummary.queryByText(alertWithGroupsAndTags.fields[ALERT_EVALUATION_THRESHOLD]!)); }); }); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx index 20d0fb36f9f8a..82c22626aab85 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx @@ -5,24 +5,97 @@ * 2.0. */ -import React, { ReactNode } from 'react'; -import { EuiFlexItem, EuiFlexGroup, EuiText, EuiSpacer } from '@elastic/eui'; +import React, { useEffect, useState, ReactNode } from 'react'; +import { EuiFlexItem, EuiFlexGroup, EuiText, EuiSpacer, EuiLink } from '@elastic/eui'; +import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; +import { + TAGS, + ALERT_START, + ALERT_END, + ALERT_RULE_NAME, + ALERT_RULE_UUID, +} from '@kbn/rule-data-utils'; +import { i18n } from '@kbn/i18n'; +import { TimeRange } from '@kbn/es-query'; +import { TopAlert } from '../../..'; +import { Groups } from '../../../components/alert_sources/groups'; +import { Tags } from '../../../components/tags'; +import { getSources } from '../../../components/alert_sources/get_sources'; +import { useKibana } from '../../../utils/kibana_react'; +import { paths } from '../../../../common/locators/paths'; export interface AlertSummaryField { label: ReactNode | string; value: ReactNode | string | number; } interface AlertSummaryProps { + alert: TopAlert; alertSummaryFields?: AlertSummaryField[]; } -export function AlertSummary({ alertSummaryFields }: AlertSummaryProps) { +export function AlertSummary({ alert, alertSummaryFields }: AlertSummaryProps) { + const { http } = useKibana().services; + + const [timeRange, setTimeRange] = useState({ from: 'now-15m', to: 'now' }); + + const alertStart = alert.fields[ALERT_START]; + const alertEnd = alert.fields[ALERT_END]; + const ruleName = alert.fields[ALERT_RULE_NAME]; + const ruleId = alert.fields[ALERT_RULE_UUID]; + const tags = alert.fields[TAGS]; + + const ruleLink = http.basePath.prepend(paths.observability.ruleDetails(ruleId)); + const commonFieldsAtStart = []; + const commonFieldsAtEnd = []; + const groups = getSources(alert) as Array<{ field: string; value: string }>; + + useEffect(() => { + setTimeRange(getPaddedAlertTimeRange(alertStart!, alertEnd)); + }, [alertStart, alertEnd]); + + if (groups && groups.length > 0) { + commonFieldsAtStart.push({ + label: i18n.translate('xpack.observability.alertDetails.alertSummaryField.source', { + defaultMessage: 'Source', + }), + value: ( + + ), + }); + } + + if (tags && tags.length > 0) { + commonFieldsAtEnd.push({ + label: i18n.translate('xpack.observability.alertDetails.alertSummaryField.tags', { + defaultMessage: 'Tags', + }), + value: , + }); + } + + commonFieldsAtEnd.push({ + label: i18n.translate('xpack.observability.alertDetails.alertSummaryField.rule', { + defaultMessage: 'Rule', + }), + value: ( + + {ruleName} + + ), + }); + + const alertSummary = [ + ...commonFieldsAtStart, + ...(alertSummaryFields ?? []), + ...commonFieldsAtEnd, + ]; + return (
- {alertSummaryFields && alertSummaryFields.length > 0 && ( + {alertSummary && alertSummary.length > 0 && ( <> - {alertSummaryFields.map((field, idx) => { + {alertSummary.map((field, idx) => { return ( {field.label} diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/header_actions.test.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/header_actions.test.tsx index 6c07c54f60454..b3e28ba222c5a 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/header_actions.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/header_actions.test.tsx @@ -13,7 +13,7 @@ import { casesPluginMock } from '@kbn/cases-plugin/public/mocks'; import { render } from '../../../utils/test_helper'; import { useKibana } from '../../../utils/kibana_react'; import { kibanaStartMock } from '../../../utils/kibana_react.mock'; -import { alertWithTags, mockAlertUuid, untrackedAlert } from '../mock/alert'; +import { alertWithGroupsAndTags, mockAlertUuid, untrackedAlert } from '../mock/alert'; import { useFetchRule } from '../../../hooks/use_fetch_rule'; import { HeaderActions } from './header_actions'; @@ -87,8 +87,8 @@ describe('Header Actions', () => { it('should display an actions button', () => { const { queryByTestId } = render( ); @@ -109,9 +109,9 @@ describe('Header Actions', () => { const { getByTestId, findByTestId } = render( ); @@ -136,8 +136,8 @@ describe('Header Actions', () => { it('should offer a "Edit rule" button which opens the edit rule flyout', async () => { const { getByTestId, findByTestId } = render( ); @@ -150,8 +150,8 @@ describe('Header Actions', () => { it('should offer a "Mark as untracked" button which is enabled', async () => { const { queryByTestId, findByTestId } = render( ); @@ -163,8 +163,8 @@ describe('Header Actions', () => { it('should offer a "Go to rule details" button which opens the rule details page in a new tab', async () => { const { queryByTestId, findByTestId } = render( ); @@ -188,8 +188,8 @@ describe('Header Actions', () => { it("should disable the 'Edit rule' when the rule is not available/deleted", async () => { const { queryByTestId, findByTestId } = render( ); @@ -214,8 +214,8 @@ describe('Header Actions', () => { it("should disable the 'View rule details' when the rule is not available/deleted", async () => { const { queryByTestId, findByTestId } = render( ); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert.ts b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert.ts index 5f377aab47686..3474f9b40674b 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert.ts +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert.ts @@ -9,6 +9,7 @@ import { ALERT_DURATION, ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, + ALERT_GROUP, ALERT_INSTANCE_ID, ALERT_REASON, ALERT_RULE_CATEGORY, @@ -27,6 +28,7 @@ import { EVENT_ACTION, EVENT_KIND, SPACE_IDS, + TAGS, TIMESTAMP, VERSION, } from '@kbn/rule-data-utils'; @@ -75,18 +77,23 @@ export const alertDetail: AlertData = { ) as unknown as AlertData['raw'], }; -export const alertWithTags: TopAlert = { +export const alertWithGroupsAndTags: TopAlert = { ...alert, fields: { ...alert.fields, + [ALERT_GROUP]: [ + { field: 'host.name', value: 'host-0' }, + { field: 'container.id', value: 'container-0' }, + ], [ALERT_RULE_TAGS]: tags, + [TAGS]: tags, }, }; export const untrackedAlert: TopAlert = { - ...alertWithTags, + ...alertWithGroupsAndTags, fields: { - ...alertWithTags.fields, + ...alertWithGroupsAndTags.fields, [ALERT_STATUS]: ALERT_STATUS_UNTRACKED, }, }; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert_summary_fields.ts b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert_summary_fields.ts index 304f750009e8d..b80890c7f73af 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert_summary_fields.ts +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/mock/alert_summary_fields.ts @@ -5,20 +5,17 @@ * 2.0. */ -import { alertWithTags } from './alert'; +import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE } from '@kbn/rule-data-utils'; +import { alertWithGroupsAndTags } from './alert'; import type { AlertSummaryField } from '../components/alert_summary'; export const alertSummaryFieldsMock: AlertSummaryField[] = [ { label: 'Actual value', - value: alertWithTags.fields['kibana.alert.evaluation.value']!, + value: alertWithGroupsAndTags.fields[ALERT_EVALUATION_VALUE]!, }, { label: 'Expected value', - value: alertWithTags.fields['kibana.alert.evaluation.threshold']!, - }, - { - label: 'Source', - value: '-', + value: alertWithGroupsAndTags.fields[ALERT_EVALUATION_THRESHOLD]!, }, ]; diff --git a/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts b/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts index 94be15415abb8..baec846b71154 100644 --- a/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts +++ b/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts @@ -17,7 +17,6 @@ import { LocatorPublic } from '@kbn/share-plugin/common'; import { RecoveredActionGroup } from '@kbn/alerting-plugin/common'; import { IBasePath, Logger } from '@kbn/core/server'; import { AlertsClientError, RuleExecutorOptions } from '@kbn/alerting-plugin/server'; -import { Group } from '../../../../common/custom_threshold_rule/types'; import { getEvaluationValues, getThreshold } from './lib/get_values'; import { AlertsLocatorParams, getAlertDetailsUrl } from '../../../../common'; import { getViewInAppUrl } from '../../../../common/custom_threshold_rule/get_view_in_app_url'; @@ -46,6 +45,7 @@ import { import { formatAlertResult, getLabel } from './lib/format_alert_result'; import { EvaluatedRuleParams, evaluateRule } from './lib/evaluate_rule'; import { MissingGroupsRecord } from './lib/check_missing_group'; +import { Group } from '../../../../common/typings'; export interface CustomThresholdLocators { alertsLocator?: LocatorPublic; diff --git a/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/types.ts b/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/types.ts index 6f1e8cf72cc7d..052741c474f46 100644 --- a/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/types.ts +++ b/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/types.ts @@ -18,9 +18,9 @@ import { ALERT_EVALUATION_VALUES, ALERT_GROUP, } from '@kbn/rule-data-utils'; +import { Group } from '../../../../common/typings'; import { CustomMetricExpressionParams, - Group, SearchConfigurationWithExtractedReferenceType, } from '../../../../common/custom_threshold_rule/types'; import { FIRED_ACTIONS_ID, NO_DATA_ACTIONS_ID, FIRED_ACTION, NO_DATA_ACTION } from './constants'; diff --git a/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/utils.ts b/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/utils.ts index 88f1febca71c0..c80a003c050e0 100644 --- a/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/utils.ts +++ b/x-pack/plugins/observability_solution/observability/server/lib/rules/custom_threshold/utils.ts @@ -17,7 +17,7 @@ import { set } from '@kbn/safer-lodash-set'; import { ParsedExperimentalFields } from '@kbn/rule-registry-plugin/common/parse_experimental_fields'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import { Alert } from '@kbn/alerts-as-data-utils'; -import type { Group } from '../../../../common/custom_threshold_rule/types'; +import type { Group } from '../../../../common/typings'; import { ObservabilityConfig } from '../../..'; import { AlertExecutionDetails } from './types'; diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx index 324c84c9d923f..be83b74a0cc19 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/burn_rate/alert_details/alert_details_app_section.tsx @@ -7,10 +7,8 @@ import { EuiFlexGroup, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AlertSummaryField } from '@kbn/observability-plugin/public'; -import { ALL_VALUE } from '@kbn/slo-schema'; import React, { useEffect } from 'react'; import { useFetchSloDetails } from '../../../../hooks/use_fetch_slo_details'; -import { SLOGroupings } from '../../../../pages/slos/components/common/slo_groupings'; import { useKibana } from '../../../../utils/kibana_react'; import { CustomAlertDetailsPanel } from './components/custom_panels/custom_panels'; import { ErrorRatePanel } from './components/error_rate/error_rate_panel'; @@ -19,7 +17,6 @@ import { BurnRateAlert, BurnRateRule } from './types'; interface AppSectionProps { alert: BurnRateAlert; rule: BurnRateRule; - ruleLink: string; setAlertSummaryFields: React.Dispatch>; } @@ -27,7 +24,6 @@ interface AppSectionProps { export default function AlertDetailsAppSection({ alert, rule, - ruleLink, setAlertSummaryFields, }: AppSectionProps) { const { @@ -45,7 +41,7 @@ export default function AlertDetailsAppSection({ const fields = [ { label: i18n.translate('xpack.slo.burnRateRule.alertDetailsAppSection.summaryField.slo', { - defaultMessage: 'Source SLO', + defaultMessage: 'SLO', }), value: ( @@ -53,30 +49,10 @@ export default function AlertDetailsAppSection({ ), }, - { - label: i18n.translate('xpack.slo.burnRateRule.alertDetailsAppSection.summaryField.rule', { - defaultMessage: 'Rule', - }), - value: ( - - {rule.name} - - ), - }, ]; - if (instanceId !== ALL_VALUE) { - fields.push({ - label: i18n.translate( - 'xpack.slo.burnRateRule.alertDetailsAppSection.summaryField.instanceId', - { defaultMessage: 'SLO Instance' } - ), - value: , - }); - } - setAlertSummaryFields(fields); - }, [alertLink, rule, ruleLink, setAlertSummaryFields, basePath, slo, instanceId]); + }, [alertLink, rule, setAlertSummaryFields, basePath, slo, instanceId]); return ( diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.test.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.test.ts index ebbfff071bbe3..1b3ddb32c56f8 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.test.ts @@ -9,7 +9,6 @@ import { SanitizedRuleConfig } from '@kbn/alerting-plugin/common'; import { DEFAULT_FLAPPING_SETTINGS } from '@kbn/alerting-plugin/common/rules_settings'; import { RuleExecutorServices } from '@kbn/alerting-plugin/server'; import { publicAlertsClientMock } from '@kbn/alerting-plugin/server/alerts_client/alerts_client.mock'; -import { ObservabilitySloAlert } from '@kbn/alerts-as-data-utils'; import { IBasePath, IUiSettingsClient, @@ -47,6 +46,7 @@ import { import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, + ALERT_GROUP, ALERT_REASON, SLO_BURN_RATE_RULE_TYPE_ID, } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; @@ -54,7 +54,7 @@ import { SLODefinition, StoredSLODefinition } from '../../../domain/models'; import { SLONotFound } from '../../../errors'; import { SO_SLO_TYPE } from '../../../saved_objects'; import { createSLO } from '../../../services/fixtures/slo'; -import { getRuleExecutor } from './executor'; +import { BurnRateAlert, getRuleExecutor } from './executor'; import { generateAboveThresholdKey, generateBurnRateKey, @@ -163,7 +163,7 @@ describe('BurnRateRuleExecutor', () => { BurnRateAlertState, BurnRateAlertContext, BurnRateAllowedActionGroups, - ObservabilitySloAlert + BurnRateAlert > >; @@ -338,7 +338,7 @@ describe('BurnRateRuleExecutor', () => { }); it('schedules an alert when both windows of first window definition burn rate have reached the threshold', async () => { - const slo = createSLO({ objective: { target: 0.9 } }); + const slo = createSLO({ objective: { target: 0.9 }, groupBy: ['group.by.field'] }); const ruleParams = someRuleParamsWithWindows({ sloId: slo.id }); soClientMock.find.mockResolvedValueOnce(createFindResponse([slo])); const buckets = [ @@ -404,6 +404,12 @@ describe('BurnRateRuleExecutor', () => { [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: 'foo', + [ALERT_GROUP]: [ + { + field: 'group.by.field', + value: 'foo', + }, + ], }, }); expect(servicesMock.alertsClient?.report).toBeCalledWith({ @@ -420,6 +426,12 @@ describe('BurnRateRuleExecutor', () => { [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: 'bar', + [ALERT_GROUP]: [ + { + field: 'group.by.field', + value: 'bar', + }, + ], }, }); expect(servicesMock.alertsClient?.setAlertData).toHaveBeenNthCalledWith(1, { @@ -454,7 +466,7 @@ describe('BurnRateRuleExecutor', () => { }); it('schedules a suppressed alert when both windows of first window definition burn rate have reached the threshold but the dependency matches', async () => { - const slo = createSLO({ objective: { target: 0.9 } }); + const slo = createSLO({ objective: { target: 0.9 }, groupBy: ['group.by.field'] }); const dependencyRuleParams = someRuleParamsWithWindows({ sloId: slo.id }); const ruleParams = someRuleParamsWithWindows({ sloId: slo.id, @@ -538,6 +550,12 @@ describe('BurnRateRuleExecutor', () => { [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: 'foo', + [ALERT_GROUP]: [ + { + field: 'group.by.field', + value: 'foo', + }, + ], }, }); expect(servicesMock.alertsClient?.report).toBeCalledWith({ @@ -554,6 +572,12 @@ describe('BurnRateRuleExecutor', () => { [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: 'bar', + [ALERT_GROUP]: [ + { + field: 'group.by.field', + value: 'bar', + }, + ], }, }); expect(servicesMock.alertsClient?.setAlertData).toHaveBeenNthCalledWith(1, { @@ -588,7 +612,7 @@ describe('BurnRateRuleExecutor', () => { }); it('schedules an alert when both windows of second window definition burn rate have reached the threshold', async () => { - const slo = createSLO({ objective: { target: 0.9 } }); + const slo = createSLO({ objective: { target: 0.9 }, groupBy: ['group.by.field'] }); const ruleParams = someRuleParamsWithWindows({ sloId: slo.id }); soClientMock.find.mockResolvedValueOnce(createFindResponse([slo])); const buckets = [ @@ -653,6 +677,12 @@ describe('BurnRateRuleExecutor', () => { [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: 'foo', + [ALERT_GROUP]: [ + { + field: 'group.by.field', + value: 'foo', + }, + ], }, }); expect(servicesMock.alertsClient!.report).toBeCalledWith({ @@ -669,6 +699,12 @@ describe('BurnRateRuleExecutor', () => { [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: 'bar', + [ALERT_GROUP]: [ + { + field: 'group.by.field', + value: 'bar', + }, + ], }, }); diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts index 0df4a07fa70c1..1e4be6e78b88e 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/executor.ts @@ -10,6 +10,7 @@ import numeral from '@elastic/numeral'; import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, + ALERT_GROUP, ALERT_REASON, } from '@kbn/rule-data-utils'; import { AlertsClientError, RuleExecutorOptions } from '@kbn/alerting-plugin/server'; @@ -36,6 +37,7 @@ import { BurnRateAllowedActionGroups, BurnRateRuleParams, BurnRateRuleTypeState, + Group, WindowSchema, } from './types'; import { @@ -50,6 +52,10 @@ import { evaluateDependencies } from './lib/evaluate_dependencies'; import { shouldSuppressInstanceId } from './lib/should_suppress_instance_id'; import { getSloSummary } from './lib/summary_repository'; +export type BurnRateAlert = Omit & { + [ALERT_GROUP]?: Group[]; +}; + export const getRuleExecutor = ({ basePath, alertsLocator, @@ -64,7 +70,7 @@ export const getRuleExecutor = ({ BurnRateAlertState, BurnRateAlertContext, BurnRateAllowedActionGroups, - ObservabilitySloAlert + BurnRateAlert > ): ReturnType< ExecutorType< @@ -123,6 +129,15 @@ export const getRuleExecutor = ({ window: windowDef, } = result; + const instances = instanceId.split(','); + const groups = + instanceId !== ALL_VALUE + ? [slo.groupBy].flat().reduce((resultGroups, groupByItem, index) => { + resultGroups.push({ field: groupByItem, value: instances[index].trim() }); + return resultGroups; + }, []) + : undefined; + const urlQuery = instanceId === ALL_VALUE ? '' : `?instanceId=${instanceId}`; const viewInAppUrl = addSpaceIdToPath( basePath.publicBaseUrl, @@ -165,6 +180,7 @@ export const getRuleExecutor = ({ [ALERT_REASON]: reason, [ALERT_EVALUATION_THRESHOLD]: windowDef.burnRateThreshold, [ALERT_EVALUATION_VALUE]: Math.min(longWindowBurnRate, shortWindowBurnRate), + [ALERT_GROUP]: groups, [SLO_ID_FIELD]: slo.id, [SLO_REVISION_FIELD]: slo.revision, [SLO_INSTANCE_ID_FIELD]: instanceId, diff --git a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/types.ts b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/types.ts index be7442749d625..c63306fb0df26 100644 --- a/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/types.ts +++ b/x-pack/plugins/observability_solution/slo/server/lib/rules/slo_burn_rate/types.ts @@ -52,3 +52,8 @@ export type BurnRateAllowedActionGroups = ActionGroupIdsOf< | typeof LOW_PRIORITY_ACTION | typeof SUPPRESSED_PRIORITY_ACTION >; + +export interface Group { + field: string; + value: string; +} diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index fd47cd081f878..673bfbcfe49ff 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -9436,8 +9436,6 @@ "xpack.apm.onboarding.shared_clients.configure.commands.serviceNameHint": "Le nom de service est le filtre principal dans l'interface utilisateur APM et est utilisé pour regrouper les erreurs et suivre les données ensemble. Caractères autorisés : a-z, A-Z, 0-9, -, _ et espace.", "xpack.apm.pages.alertDetails.alertSummary.actualValue": "Valeur réelle", "xpack.apm.pages.alertDetails.alertSummary.expectedValue": "Valeur attendue", - "xpack.apm.pages.alertDetails.alertSummary.serviceEnv": "Environnement de service", - "xpack.apm.pages.alertDetails.alertSummary.serviceName": "Nom de service", "xpack.apm.profiling.callout.description": "Universal Profiling fournit une visibilité sans précédent du code au milieu du comportement en cours d'exécution de toutes les applications. La fonctionnalité profile chaque ligne de code chez le ou les hôtes qui exécutent vos services, y compris votre code applicatif, le kernel et même les bibliothèque tierces.", "xpack.apm.profiling.callout.dismiss": "Rejeter", "xpack.apm.profiling.callout.learnMore": "En savoir plus", @@ -21393,7 +21391,6 @@ "xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.chartLabel": "Âge", "xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.sectionLabel": "Message le plus ancien", "xpack.infra.metricDetailPage.sqsMetricsLayout.overviewSection.sectionLabel": "Aperçu SQS AWS", - "xpack.infra.metrics.alertDetailsAppSection.summaryField.rule": "Règle", "xpack.infra.metrics.alertDetailsAppSection.thresholdTitle": "Seuil dépassé", "xpack.infra.metrics.alertFlyout.addCondition": "Ajouter une condition", "xpack.infra.metrics.alertFlyout.addWarningThreshold": "Ajouter un seuil d'avertissement", @@ -29585,7 +29582,6 @@ "xpack.observability.customThreshold.rule.aggregators.p99": "99e centile de {metric}", "xpack.observability.customThreshold.rule.aggregators.rate": "Taux de {metric}", "xpack.observability.customThreshold.rule.aggregators.sum": "Somme de {metric}", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags": "+{number} de plus", "xpack.observability.customThreshold.rule.alertFlyout.alertPerRedundantFilterError": "Il est possible que cette règle signale {matchedGroups} moins que prévu, car la requête de filtre comporte une correspondance pour {groupCount, plural, one {ce champ} other {ces champs}}. Pour en savoir plus, veuillez consulter {filteringAndGroupingLink}.", "xpack.observability.customThreshold.rule.alertFlyout.condition": "Condition {conditionNumber}", "xpack.observability.customThreshold.rule.alertFlyout.customEquationEditor.aggregationLabel": "{name} de l'agrégation", @@ -29700,10 +29696,6 @@ "xpack.observability.customThreshold.rule..timeLabels.seconds": "secondes", "xpack.observability.customThreshold.rule.aggregators.customEquation": "Équation personnalisée", "xpack.observability.customThreshold.rule.aggregators.documentCount": "Nombre de documents", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags.ariaLabel": "badge plus de balises", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.rule": "Règle", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.source": "Source", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.tags": "Balises", "xpack.observability.customThreshold.rule.alertDetailsAppSection.thresholdTitle": "Seuil dépassé", "xpack.observability.customThreshold.rule.alertDetailUrlActionVariableDescription": "Lien vers l’affichage de résolution des problèmes d’alerte pour voir plus de contextes et de détails. La chaîne sera vide si server.publicBaseUrl n'est pas configuré.", "xpack.observability.customThreshold.rule.alertFlyout.addCondition": "Ajouter une condition", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7e2f411d770c2..56df15a9c73bd 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9416,8 +9416,6 @@ "xpack.apm.onboarding.shared_clients.configure.commands.serviceNameHint": "このサービス名はAPM UIの主フィルターであり、エラーとトレースデータをグループ化するために使用されます。使用できる文字はA-Z、0-9、-、_、スペースです。", "xpack.apm.pages.alertDetails.alertSummary.actualValue": "実際の値", "xpack.apm.pages.alertDetails.alertSummary.expectedValue": "想定された値", - "xpack.apm.pages.alertDetails.alertSummary.serviceEnv": "サービス環境", - "xpack.apm.pages.alertDetails.alertSummary.serviceName": "サービス名", "xpack.apm.profiling.callout.description": "ユニバーサルプロファイリングは、すべてのアプリケーションの実行時の動作に関して、かつてないほどコードを可視化します。アプリケーションコードだけでなく、カーネルやサードパーティライブラリも含め、サービスを実行するホスト上のすべてのコード行をプロファイリングします。", "xpack.apm.profiling.callout.dismiss": "閉じる", "xpack.apm.profiling.callout.learnMore": "詳細", @@ -21368,7 +21366,6 @@ "xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.chartLabel": "年齢", "xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.sectionLabel": "最も古いメッセージ", "xpack.infra.metricDetailPage.sqsMetricsLayout.overviewSection.sectionLabel": "Aws SQS概要", - "xpack.infra.metrics.alertDetailsAppSection.summaryField.rule": "ルール", "xpack.infra.metrics.alertDetailsAppSection.thresholdTitle": "しきい値を超えました", "xpack.infra.metrics.alertFlyout.addCondition": "条件を追加", "xpack.infra.metrics.alertFlyout.addWarningThreshold": "警告しきい値を追加", @@ -29562,7 +29559,6 @@ "xpack.observability.customThreshold.rule.aggregators.p99": "{metric}の99パーセンタイル", "xpack.observability.customThreshold.rule.aggregators.rate": "{metric}の比率", "xpack.observability.customThreshold.rule.aggregators.sum": "{metric}の合計", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags": "その他{number}", "xpack.observability.customThreshold.rule.alertFlyout.alertPerRedundantFilterError": "このルールは想定未満の{matchedGroups}に対してアラートを通知できます。フィルタークエリには{groupCount, plural, one {このフィールド} other {これらのフィールド}}の完全一致が含まれるためです。詳細については、{filteringAndGroupingLink}を参照してください。", "xpack.observability.customThreshold.rule.alertFlyout.condition": "条件{conditionNumber}", "xpack.observability.customThreshold.rule.alertFlyout.customEquationEditor.aggregationLabel": "集約{name}", @@ -29678,10 +29674,6 @@ "xpack.observability.customThreshold.rule..timeLabels.seconds": "秒", "xpack.observability.customThreshold.rule.aggregators.customEquation": "カスタム等式", "xpack.observability.customThreshold.rule.aggregators.documentCount": "ドキュメントカウント", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags.ariaLabel": "その他のタグバッジ", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.rule": "ルール", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.source": "送信元", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.tags": "タグ", "xpack.observability.customThreshold.rule.alertDetailsAppSection.thresholdTitle": "しきい値を超えました", "xpack.observability.customThreshold.rule.alertDetailUrlActionVariableDescription": "アラートトラブルシューティングビューにリンクして、さらに詳しい状況や詳細を確認できます。server.publicBaseUrlが構成されていない場合は、空の文字列になります。", "xpack.observability.customThreshold.rule.alertFlyout.addCondition": "条件を追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d43efdcf980fb..48d126c33a1e9 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9439,8 +9439,6 @@ "xpack.apm.onboarding.shared_clients.configure.commands.serviceNameHint": "服务名称是 APM UI 中的初级筛选,用于分组错误并跟踪数据。允许使用的字符包括 a-z、A-Z、0-9、-、_ 和空格。", "xpack.apm.pages.alertDetails.alertSummary.actualValue": "实际值", "xpack.apm.pages.alertDetails.alertSummary.expectedValue": "预期值", - "xpack.apm.pages.alertDetails.alertSummary.serviceEnv": "服务环境", - "xpack.apm.pages.alertDetails.alertSummary.serviceName": "服务名称", "xpack.apm.profiling.callout.description": "Universal Profiling 为所有应用程序的运行时行为提供了前所未有的代码可见性。它会剖析运行服务的主机上的每一行代码,不仅包括您的应用程序代码,而且包括内核和第三方库。", "xpack.apm.profiling.callout.dismiss": "关闭", "xpack.apm.profiling.callout.learnMore": "了解详情", @@ -21400,7 +21398,6 @@ "xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.chartLabel": "存在时间", "xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.sectionLabel": "最旧消息", "xpack.infra.metricDetailPage.sqsMetricsLayout.overviewSection.sectionLabel": "Aws SQS 概览", - "xpack.infra.metrics.alertDetailsAppSection.summaryField.rule": "规则", "xpack.infra.metrics.alertDetailsAppSection.thresholdTitle": "超出阈值", "xpack.infra.metrics.alertFlyout.addCondition": "添加条件", "xpack.infra.metrics.alertFlyout.addWarningThreshold": "添加警告阈值", @@ -29602,7 +29599,6 @@ "xpack.observability.customThreshold.rule.aggregators.p99": "{metric} 的第 99 个百分位", "xpack.observability.customThreshold.rule.aggregators.rate": "{metric} 的比率", "xpack.observability.customThreshold.rule.aggregators.sum": "{metric} 的总和", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags": "+ 另外 {number} 个", "xpack.observability.customThreshold.rule.alertFlyout.alertPerRedundantFilterError": "此规则可能针对低于预期的 {matchedGroups} 告警,因为筛选查询包含{groupCount, plural, one {此字段} other {这些字段}}的匹配项。有关更多信息,请参阅 {filteringAndGroupingLink}。", "xpack.observability.customThreshold.rule.alertFlyout.condition": "条件 {conditionNumber}", "xpack.observability.customThreshold.rule.alertFlyout.customEquationEditor.aggregationLabel": "聚合 {name}", @@ -29718,10 +29714,6 @@ "xpack.observability.customThreshold.rule..timeLabels.seconds": "秒", "xpack.observability.customThreshold.rule.aggregators.customEquation": "定制方程", "xpack.observability.customThreshold.rule.aggregators.documentCount": "文档计数", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.moreTags.ariaLabel": "更多标签徽章", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.rule": "规则", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.source": "源", - "xpack.observability.customThreshold.rule.alertDetailsAppSection.summaryField.tags": "标签", "xpack.observability.customThreshold.rule.alertDetailsAppSection.thresholdTitle": "超出阈值", "xpack.observability.customThreshold.rule.alertDetailUrlActionVariableDescription": "链接到告警故障排除视图获取进一步的上下文和详情。如果未配置 server.publicBaseUrl,这将为空字符串。", "xpack.observability.customThreshold.rule.alertFlyout.addCondition": "添加条件", From f820f788072ebd48613ee0b8074abf06605263f7 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:21:48 -0400 Subject: [PATCH 044/127] [Security Solution][Endpoint] Refactor UI response actions code (#184543) ## Summary This PR does a major refactor of Response Actions functionality usage outside of the `management` section of the code base. The impact (although should be transparent from a user's standpoint) is mostly to the Alert Details "Take Action" menu and specifically to the "Isolate/Release" and "Respond" menu actions and the UI's it displays when clicked. The changes can be summarized as: - Centralized (moved) all code associated with Response Actions under one of the following three directories: - `public/common/component/endpoint` - `public/common/hooks/endpoint` - `public/common/lib/endpoint` - Most changed files in this PR were a result of this activity - Deleted several utilities that were used to determine the Alert's host support for Response actions and replaced with a single `hook` (`useAlertResponseActionsSupport()`) - The "Isolate/Release" Take Action menu item now behaves similar to the "Respond" menu option (on Alerts) in that: - Its only NOT displayed if the user is not authorized to use it - It will show up as disabled while we are attempting to determine support for response actions on the alert's host - Tooltips will be displayed when options is disabled --- .github/CODEOWNERS | 11 +- .../service/host_isolation/utils.test.ts | 84 ----- .../endpoint/service/host_isolation/utils.ts | 83 ----- .../service/response_actions/constants.ts | 11 + .../public/cases/pages/index.tsx | 2 +- .../agent_response_action_status.tsx | 8 +- .../agents/agent_status/agent_status.test.tsx | 14 +- .../agents/agent_status/agent_status.tsx | 12 +- .../endpoint/endpoint_agent_status.test.tsx | 24 +- .../endpoint/endpoint_agent_status.tsx | 16 +- .../agents/agent_status/index.ts | 0 .../agents/agent_status_text.ts | 2 +- .../host_isolation/__mocks__}/index.ts | 2 +- .../from_alerts/__mocks__/index.ts | 8 + .../__mocks__/use_host_isolation_action.tsx | 23 ++ .../host_isolation_panel.test.tsx} | 44 +-- .../from_alerts/host_isolation_panel.tsx | 74 +++++ .../host_isolation/from_alerts/index.ts | 10 + .../host_isolation/from_alerts}/isolate.tsx | 13 +- .../from_alerts}/translations.ts | 0 .../host_isolation/from_alerts}/unisolate.tsx | 13 +- .../from_alerts}/use_host_isolation.tsx | 8 +- .../use_host_isolation_action.test.tsx | 144 +++++++++ .../from_alerts/use_host_isolation_action.tsx | 175 +++++++++++ .../use_host_isolation_status.tsx | 26 +- .../from_alerts}/use_host_unisolation.tsx | 8 +- .../endpoint_host_isolation_cases_context.tsx | 0 .../host_isolation/from_cases/index.ts | 8 + .../endpoint/host_isolation/index.ts | 2 + .../common/components/endpoint/index.ts | 11 + .../endpoint/responder/__mocks__/index.ts | 8 + .../responder/from_alerts/__mocks__/index.ts | 9 + .../__mocks__/use_responder_action_data.ts | 24 ++ .../__mocks__/use_responder_action_item.tsx | 24 ++ .../endpoint/responder/from_alerts/index.ts | 11 + .../from_alerts}/responder_action_button.tsx | 15 +- .../responder/from_alerts}/translations.ts | 21 -- .../use_responder_action_data.test.ts | 283 +++++++++++++++++ .../from_alerts/use_responder_action_data.ts | 271 +++++++++++++++++ .../use_responder_action_item.test.tsx | 61 ++++ .../use_responder_action_item.tsx | 44 +-- .../components/endpoint/responder/index.ts | 8 + .../get_alert_summary_rows.test.ts | 156 +++------- .../event_details/get_alert_summary_rows.tsx | 78 ++--- .../components/event_details/helpers.tsx | 7 +- .../use_alert_response_actions_support.ts | 35 +++ ...use_alert_response_actions_support.test.ts | 207 +++++++++++++ .../use_alert_response_actions_support.ts | 241 +++++++++++++++ .../endpoint_isolation/index.test.ts | 6 +- .../endpoint_isolation/index.ts | 8 +- .../endpoint_isolation/mocks.ts | 8 +- .../endpoint_pending_actions.test.ts | 6 +- .../endpoint_pending_actions.ts | 8 +- .../endpoint_pending_actions/index.ts | 0 .../endpoint_pending_actions/mocks.ts | 8 +- .../public/common/lib/endpoint/index.ts | 10 + .../utils/get_event_details_field_values.ts} | 32 +- .../public/common/lib/endpoint/utils/index.ts | 9 + ...is_agent_type_and_action_supported.test.ts | 82 +++++ .../is_agent_type_and_action_supported.ts | 60 ++++ ...s_response_actions_alert_agent_id_field.ts | 19 ++ .../mock/endpoint/endpoint_alert_data_mock.ts | 248 +++++++++++++++ .../public/common/mock/endpoint/index.ts | 2 + .../public/common/translations.ts | 2 +- .../utils/crowdstrike_alert_check.test.ts | 69 ----- .../common/utils/crowdstrike_alert_check.ts | 69 ----- .../common/utils/endpoint_alert_check.test.ts | 85 ------ .../common/utils/endpoint_alert_check.ts | 53 ---- .../common/utils/sentinelone_alert_check.ts | 64 ---- .../timeline_actions/alert_context_menu.tsx | 12 +- .../get_external_edr_agent_info.test.ts | 120 -------- .../get_external_edr_agent_info.ts | 70 ----- .../use_responder_action_data.test.ts | 233 -------------- .../use_responder_action_data.ts | 175 ----------- .../use_responder_action_item.test.tsx | 144 --------- .../components/host_isolation/index.tsx | 94 ------ .../use_host_isolation_action.test.tsx | 163 ---------- .../use_host_isolation_action.tsx | 272 ----------------- .../take_action_dropdown/index.test.tsx | 287 +++--------------- .../components/take_action_dropdown/index.tsx | 26 +- .../containers/detection_engine/alerts/api.ts | 2 +- .../explore/hosts/pages/details/index.tsx | 4 +- .../document_details/isolate_host/content.tsx | 6 +- .../isolate_host/header.test.tsx | 169 +++++------ .../document_details/isolate_host/header.tsx | 49 ++- .../components/highlighted_fields_cell.tsx | 9 +- .../hooks/use_highlighted_fields.test.tsx | 8 +- .../shared/hooks/use_highlighted_fields.ts | 36 +-- .../fields/endpoint_policy_fields.tsx | 2 +- .../status_action.tsx | 2 +- .../header_info/agent_info/agent_info.tsx | 2 +- .../endpoint/header_endpoint_info.tsx | 2 +- .../sentinel_one/header_sentinel_one_info.tsx | 2 +- .../components/offline_callout.tsx | 23 +- .../lib/console_commands_definition.ts | 79 ++--- ...se_get_endpoint_pending_actions_summary.ts | 2 +- .../use_send_isolate_endpoint_request.ts | 2 +- .../use_send_release_endpoint_request.ts | 2 +- .../management/pages/endpoint_hosts/mocks.ts | 4 +- .../endpoint_hosts/store/middleware.test.ts | 2 +- .../pages/endpoint_hosts/store/middleware.ts | 4 +- .../store/mock_endpoint_result_list.ts | 2 +- .../view/details/endpoint_details_content.tsx | 2 +- .../view/hooks/use_endpoint_action_items.tsx | 8 +- .../pages/endpoint_hosts/view/index.test.tsx | 2 +- .../pages/endpoint_hosts/view/index.tsx | 2 +- .../host_overview/endpoint_overview/index.tsx | 2 +- .../flyout/back_to_alert_details_link.tsx | 2 +- .../side_panel/event_details/flyout/body.tsx | 6 +- .../event_details/flyout/footer.test.tsx | 19 +- .../event_details/flyout/footer.tsx | 7 +- .../event_details/flyout/header.tsx | 4 +- .../side_panel/event_details/helpers.tsx | 31 +- .../side_panel/event_details/index.test.tsx | 14 +- .../side_panel/event_details/index.tsx | 6 +- .../use_host_isolation_tools.tsx | 2 +- .../body/renderers/formatted_field.tsx | 6 +- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../alert_details_right_panel.cy.ts | 8 +- 121 files changed, 2591 insertions(+), 2732 deletions(-) delete mode 100644 x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.test.ts delete mode 100644 x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.ts rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status/agent_response_action_status.tsx (95%) rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status/agent_status.test.tsx (93%) rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status/agent_status.tsx (84%) rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status/endpoint/endpoint_agent_status.test.tsx (92%) rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status/endpoint/endpoint_agent_status.tsx (91%) rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status/index.ts (100%) rename x-pack/plugins/security_solution/public/common/components/{ => endpoint}/agents/agent_status_text.ts (90%) rename x-pack/plugins/security_solution/public/{detections/components/endpoint_responder => common/components/endpoint/host_isolation/__mocks__}/index.ts (78%) create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/use_host_isolation_action.tsx rename x-pack/plugins/security_solution/public/{detections/components/host_isolation/index.test.tsx => common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.test.tsx} (69%) create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/index.ts rename x-pack/plugins/security_solution/public/{detections/components/host_isolation => common/components/endpoint/host_isolation/from_alerts}/isolate.tsx (85%) rename x-pack/plugins/security_solution/public/{detections/components/host_isolation => common/components/endpoint/host_isolation/from_alerts}/translations.ts (100%) rename x-pack/plugins/security_solution/public/{detections/components/host_isolation => common/components/endpoint/host_isolation/from_alerts}/unisolate.tsx (85%) rename x-pack/plugins/security_solution/public/{detections/containers/detection_engine/alerts => common/components/endpoint/host_isolation/from_alerts}/use_host_isolation.tsx (78%) create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.tsx rename x-pack/plugins/security_solution/public/{detections/containers/detection_engine/alerts => common/components/endpoint/host_isolation/from_alerts}/use_host_isolation_status.tsx (83%) rename x-pack/plugins/security_solution/public/{detections/containers/detection_engine/alerts => common/components/endpoint/host_isolation/from_alerts}/use_host_unisolation.tsx (77%) rename x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/{ => from_cases}/endpoint_host_isolation_cases_context.tsx (100%) create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_cases/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_data.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_item.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/index.ts rename x-pack/plugins/security_solution/public/{detections/components/endpoint_responder => common/components/endpoint/responder/from_alerts}/responder_action_button.tsx (76%) rename x-pack/plugins/security_solution/public/{detections/components/endpoint_responder => common/components/endpoint/responder/from_alerts}/translations.ts (59%) create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.test.tsx rename x-pack/plugins/security_solution/public/{detections/components/endpoint_responder => common/components/endpoint/responder/from_alerts}/use_responder_action_item.tsx (52%) create mode 100644 x-pack/plugins/security_solution/public/common/components/endpoint/responder/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/hooks/endpoint/__mocks__/use_alert_response_actions_support.ts create mode 100644 x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.test.ts create mode 100644 x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_isolation/index.test.ts (91%) rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_isolation/index.ts (84%) rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_isolation/mocks.ts (81%) rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_pending_actions/endpoint_pending_actions.test.ts (88%) rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_pending_actions/endpoint_pending_actions.ts (77%) rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_pending_actions/index.ts (100%) rename x-pack/plugins/security_solution/public/common/lib/{ => endpoint}/endpoint_pending_actions/mocks.ts (82%) create mode 100644 x-pack/plugins/security_solution/public/common/lib/endpoint/index.ts rename x-pack/plugins/security_solution/public/{detections/components/host_isolation/helpers.ts => common/lib/endpoint/utils/get_event_details_field_values.ts} (64%) create mode 100644 x-pack/plugins/security_solution/public/common/lib/endpoint/utils/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.test.ts create mode 100644 x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.ts create mode 100644 x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_response_actions_alert_agent_id_field.ts create mode 100644 x-pack/plugins/security_solution/public/common/mock/endpoint/endpoint_alert_data_mock.ts delete mode 100644 x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.test.ts delete mode 100644 x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.ts delete mode 100644 x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts delete mode 100644 x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts delete mode 100644 x-pack/plugins/security_solution/public/common/utils/sentinelone_alert_check.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.test.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.test.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/detections/components/host_isolation/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dad6ef851a117..44c2a4f27636b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1513,6 +1513,8 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/ /x-pack/plugins/stack_connectors/public/connector_types/sentinelone @elastic/security-defend-workflows /x-pack/plugins/stack_connectors/server/connector_types/sentinelone @elastic/security-defend-workflows /x-pack/plugins/stack_connectors/common/sentinelone @elastic/security-defend-workflows +/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike @elastic/security-defend-workflows +/x-pack/plugins/stack_connectors/common/crowdstrike @elastic/security-defend-workflows ## Security Solution shared OAS schemas /x-pack/plugins/security_solution/common/api/model @elastic/security-detection-rule-management @elastic/security-detection-engine @@ -1596,12 +1598,14 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/ ## Security Solution sub teams - security-defend-workflows /x-pack/plugins/security_solution/public/management/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/public/common/lib/endpoint*/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/public/common/components/agents/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/lib/endpoint/ @elastic/security-defend-workflows /x-pack/plugins/security_solution/public/common/components/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/hooks/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/mock/endpoint @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/ @elastic/security-defend-workflows /x-pack/plugins/security_solution/common/endpoint/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/server/endpoint/ @elastic/security-defend-workflows /x-pack/plugins/security_solution/common/api/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/endpoint/ @elastic/security-defend-workflows /x-pack/plugins/security_solution/server/lists_integration/endpoint/ @elastic/security-defend-workflows /x-pack/plugins/security_solution/server/lib/license/ @elastic/security-defend-workflows /x-pack/plugins/security_solution/server/fleet_integration/ @elastic/security-defend-workflows @@ -1636,6 +1640,7 @@ x-pack/plugins/security_solution/common/api/entity_analytics @elastic/security-e x-pack/test/security_solution_api_integration/test_suites/genai @elastic/security-generative-ai # Security Defend Workflows - OSQuery Ownership +x-pack/plugins/osquery @elastic/security-defend-workflows /x-pack/plugins/security_solution/common/api/detection_engine/model/rule_response_actions @elastic/security-defend-workflows /x-pack/plugins/security_solution/public/detection_engine/rule_response_actions @elastic/security-defend-workflows /x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions @elastic/security-defend-workflows diff --git a/x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.test.ts b/x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.test.ts deleted file mode 100644 index 48928fb435fec..0000000000000 --- a/x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.test.ts +++ /dev/null @@ -1,84 +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 { isVersionSupported, isOsSupported, isIsolationSupported } from './utils'; - -describe('Host Isolation utils isVersionSupported', () => { - // NOTE: the `7.15.0.8295.0` and the text current versions are invalid. - test.each` - currentVersion | minVersionRequired | expected - ${'8.14.0'} | ${'7.13.0'} | ${true} - ${'7.14.0'} | ${'7.13.0'} | ${true} - ${'7.14.1'} | ${'7.14.0'} | ${true} - ${'8.14.0'} | ${'9.14.0'} | ${false} - ${'7.13.0'} | ${'7.14.0'} | ${false} - ${'7.14.0'} | ${'7.14.1'} | ${false} - ${'7.14.0'} | ${'7.14.0'} | ${true} - ${'7.14.0-SNAPSHOT'} | ${'7.14.0'} | ${true} - ${'7.14.0-SNAPSHOT-beta'} | ${'7.14.0'} | ${true} - ${'7.14.0-alpha'} | ${'7.14.0'} | ${true} - ${'8.0.0-SNAPSHOT'} | ${'7.14.0'} | ${true} - ${'8.0.0'} | ${'7.14.0'} | ${true} - ${'7.15.0.8295.0'} | ${'7.14.0'} | ${false} - ${'NOT_SEMVER'} | ${'7.14.0'} | ${false} - `( - 'should validate that version $a is compatible($expected) to $b', - ({ currentVersion, minVersionRequired, expected }) => { - expect( - isVersionSupported({ - currentVersion, - minVersionRequired, - }) - ).toEqual(expected); - } - ); -}); - -describe('Host Isolation utils isOsSupported', () => { - test.each` - currentOs | supportedOss | expected - ${'linux'} | ${{ macos: true, linux: true }} | ${true} - ${'linux'} | ${{ macos: true, windows: true }} | ${false} - `( - 'should validate that os $a is compatible($expected) to $b', - ({ currentOs, supportedOss, expected }) => { - expect( - isOsSupported({ - currentOs, - supportedOss, - }) - ).toEqual(expected); - } - ); -}); - -describe('Host Isolation utils isIsolationSupported', () => { - test.each` - osName | version | capabilities | expected - ${'windows'} | ${'7.14.0'} | ${[]} | ${true} - ${'linux'} | ${'7.13.0'} | ${['isolation']} | ${false} - ${'linux'} | ${'7.14.0'} | ${['isolation']} | ${false} - ${'macos'} | ${'7.13.0'} | ${['isolation']} | ${false} - ${'linux'} | ${'7.13.0'} | ${['isolation']} | ${false} - ${'windows'} | ${'7.15.0'} | ${[]} | ${false} - ${'macos'} | ${'7.15.0'} | ${[]} | ${false} - ${'linux'} | ${'7.15.0'} | ${['isolation']} | ${true} - ${'macos'} | ${'7.15.0'} | ${['isolation']} | ${true} - ${'linux'} | ${'7.16.0'} | ${['isolation']} | ${true} - `( - 'should validate that os $a, version $b, and capabilities $c supports hostIsolation($expected)', - ({ osName, version, capabilities, expected }) => { - expect( - isIsolationSupported({ - osName, - version, - capabilities, - }) - ).toEqual(expected); - } - ); -}); diff --git a/x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.ts b/x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.ts deleted file mode 100644 index 97d7eb2db641f..0000000000000 --- a/x-pack/plugins/security_solution/common/endpoint/service/host_isolation/utils.ts +++ /dev/null @@ -1,83 +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 semverLte from 'semver/functions/lte'; -import type { ImmutableArray } from '../../types'; - -const minSupportedVersion = '7.14.0'; -const minCapabilitiesVersion = '7.15.0'; -const supportedOssMap = { - macos: true, - windows: true, -}; -const isolationCapability = 'isolation'; - -function parseSemver(semver: string) { - return semver.includes('-') ? semver.substring(0, semver.indexOf('-')) : semver; -} - -export const isVersionSupported = ({ - currentVersion, - minVersionRequired = minSupportedVersion, -}: { - currentVersion: string; - minVersionRequired?: string; -}) => { - // `parseSemver()` will throw if the version provided is not a valid semver value. - // If that happens, then just return false from this function - try { - const parsedCurrentVersion = parseSemver(currentVersion); - return semverLte(minVersionRequired, parsedCurrentVersion); - } catch (e) { - // If running in the browser, log to console - if (window && window.console) { - window.console.warn( - `SecuritySolution: isVersionSupported(): Unable to determine if current version [${currentVersion}] meets minimum version [${minVersionRequired}]. Error: ${e.message}` - ); - } - return false; - } -}; - -export const isOsSupported = ({ - currentOs, - supportedOss = supportedOssMap, -}: { - currentOs: string; - supportedOss?: { [os: string]: boolean }; -}) => !!supportedOss[currentOs]; - -function isCapabilitiesSupported(semver: string): boolean { - const parsedVersion = parseSemver(semver); - // capabilities is only available from 7.15+ - return semverLte(minCapabilitiesVersion, parsedVersion); -} - -function isIsolationSupportedCapabilities(capabilities: ImmutableArray = []): boolean { - return capabilities.includes(isolationCapability); -} - -// capabilities isn't introduced until 7.15 so check the OS for support -function isIsolationSupportedOS(osName: string): boolean { - const normalizedOs = osName.toLowerCase(); - return isOsSupported({ currentOs: normalizedOs }); -} - -export const isIsolationSupported = ({ - osName, - version, - capabilities, -}: { - osName: string; - version: string; - capabilities?: ImmutableArray; -}): boolean => { - if (!version || !isVersionSupported({ currentVersion: version })) return false; - - return isCapabilitiesSupported(version) - ? isIsolationSupportedCapabilities(capabilities) - : isIsolationSupportedOS(osName); -}; diff --git a/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts b/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts index 32773a3fafef4..fdfa5ed02cb73 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts @@ -174,3 +174,14 @@ export const RESPONSE_ACTIONS_ZIP_PASSCODE: Readonly +> = Object.freeze({ + endpoint: 'agent.id', + sentinel_one: 'observer.serial_number', + crowdstrike: 'crowdstrike.event.DeviceId', +}); diff --git a/x-pack/plugins/security_solution/public/cases/pages/index.tsx b/x-pack/plugins/security_solution/public/cases/pages/index.tsx index e3eb2290e6e77..54ece0123738f 100644 --- a/x-pack/plugins/security_solution/public/cases/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/pages/index.tsx @@ -10,6 +10,7 @@ import { useDispatch } from 'react-redux'; import type { CaseViewRefreshPropInterface } from '@kbn/cases-plugin/common'; import { CaseMetricsFeature } from '@kbn/cases-plugin/common'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { CaseDetailsRefreshContext } from '../../common/components/endpoint'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; import { DocumentDetailsRightPanelKey } from '../../flyout/document_details/shared/constants/panel_keys'; import { useTourContext } from '../../common/components/guided_onboarding_tour'; @@ -26,7 +27,6 @@ import { APP_ID, CASES_PATH, SecurityPageName } from '../../../common/constants' import { timelineActions } from '../../timelines/store'; import { useSourcererDataView } from '../../sourcerer/containers'; import { SourcererScopeName } from '../../sourcerer/store/model'; -import { CaseDetailsRefreshContext } from '../../common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; import { getEndpointDetailsPath } from '../../management/common/routing'; import { SpyRoute } from '../../common/utils/route/spy_routes'; diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_response_action_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_response_action_status.tsx similarity index 95% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_response_action_status.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_response_action_status.tsx index 72c3258a62863..275cc4751e6fe 100644 --- a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_response_action_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_response_action_status.tsx @@ -8,11 +8,11 @@ import React, { memo, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiTextColor, EuiToolTip } from '@elastic/eui'; -import type { EndpointPendingActions } from '../../../../../common/endpoint/types'; -import type { ResponseActionsApiCommandNames } from '../../../../../common/endpoint/service/response_actions/constants'; -import { RESPONSE_ACTION_API_COMMAND_TO_CONSOLE_COMMAND_MAP } from '../../../../../common/endpoint/service/response_actions/constants'; +import type { EndpointPendingActions } from '../../../../../../common/endpoint/types'; +import type { ResponseActionsApiCommandNames } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { RESPONSE_ACTION_API_COMMAND_TO_CONSOLE_COMMAND_MAP } from '../../../../../../common/endpoint/service/response_actions/constants'; import { ISOLATED_LABEL, ISOLATING_LABEL, RELEASING_LABEL } from './endpoint/endpoint_agent_status'; -import { useTestIdGenerator } from '../../../../management/hooks/use_test_id_generator'; +import { useTestIdGenerator } from '../../../../../management/hooks/use_test_id_generator'; const TOOLTIP_CONTENT_STYLES: React.CSSProperties = Object.freeze({ width: 150 }); diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_status.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_status.test.tsx similarity index 93% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_status.test.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_status.test.tsx index 47210272781c0..b384cf9a542a2 100644 --- a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_status.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_status.test.tsx @@ -11,17 +11,17 @@ import { AgentStatus } from './agent_status'; import { useAgentStatusHook, useGetAgentStatus, -} from '../../../../management/hooks/agents/use_get_agent_status'; +} from '../../../../../management/hooks/agents/use_get_agent_status'; import { RESPONSE_ACTION_AGENT_TYPE, type ResponseActionAgentType, -} from '../../../../../common/endpoint/service/response_actions/constants'; -import type { AppContextTestRender } from '../../../mock/endpoint'; -import { createAppRootMockRenderer } from '../../../mock/endpoint'; -import { HostStatus } from '../../../../../common/endpoint/types'; +} from '../../../../../../common/endpoint/service/response_actions/constants'; +import type { AppContextTestRender } from '../../../../mock/endpoint'; +import { createAppRootMockRenderer } from '../../../../mock/endpoint'; +import { HostStatus } from '../../../../../../common/endpoint/types'; -jest.mock('../../../hooks/use_experimental_features'); -jest.mock('../../../../management/hooks/agents/use_get_agent_status'); +jest.mock('../../../../hooks/use_experimental_features'); +jest.mock('../../../../../management/hooks/agents/use_get_agent_status'); const getAgentStatusMock = useGetAgentStatus as jest.Mock; const useAgentStatusHookMock = useAgentStatusHook as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_status.tsx similarity index 84% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_status.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_status.tsx index 363e233baab59..c4e61103e6a82 100644 --- a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/agent_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/agent_status.tsx @@ -8,12 +8,12 @@ import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useMemo } from 'react'; import styled from 'styled-components'; -import type { ResponseActionAgentType } from '../../../../../common/endpoint/service/response_actions/constants'; -import type { EndpointPendingActions } from '../../../../../common/endpoint/types'; -import { useAgentStatusHook } from '../../../../management/hooks/agents/use_get_agent_status'; -import { useTestIdGenerator } from '../../../../management/hooks/use_test_id_generator'; -import { HOST_STATUS_TO_BADGE_COLOR } from '../../../../management/pages/endpoint_hosts/view/host_constants'; -import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import type { EndpointPendingActions } from '../../../../../../common/endpoint/types'; +import { useAgentStatusHook } from '../../../../../management/hooks/agents/use_get_agent_status'; +import { useTestIdGenerator } from '../../../../../management/hooks/use_test_id_generator'; +import { HOST_STATUS_TO_BADGE_COLOR } from '../../../../../management/pages/endpoint_hosts/view/host_constants'; +import { useIsExperimentalFeatureEnabled } from '../../../../hooks/use_experimental_features'; import { getAgentStatusText } from '../agent_status_text'; import { AgentResponseActionsStatus } from './agent_response_action_status'; export enum SENTINEL_ONE_NETWORK_STATUS { diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/endpoint/endpoint_agent_status.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/endpoint/endpoint_agent_status.test.tsx similarity index 92% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status/endpoint/endpoint_agent_status.test.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/endpoint/endpoint_agent_status.test.tsx index 58ef96a42b934..40119d452d2c1 100644 --- a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/endpoint/endpoint_agent_status.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/endpoint/endpoint_agent_status.test.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import type { AppContextTestRender } from '../../../../mock/endpoint'; -import { createAppRootMockRenderer } from '../../../../mock/endpoint'; +import type { AppContextTestRender } from '../../../../../mock/endpoint'; +import { createAppRootMockRenderer } from '../../../../../mock/endpoint'; import type { EndpointAgentStatusByIdProps, EndpointAgentStatusProps, @@ -15,18 +15,18 @@ import { EndpointAgentStatus, EndpointAgentStatusById } from './endpoint_agent_s import type { EndpointPendingActions, HostInfoInterface, -} from '../../../../../../common/endpoint/types'; -import { HostStatus } from '../../../../../../common/endpoint/types'; +} from '../../../../../../../common/endpoint/types'; +import { HostStatus } from '../../../../../../../common/endpoint/types'; import React from 'react'; -import { EndpointActionGenerator } from '../../../../../../common/endpoint/data_generators/endpoint_action_generator'; -import { EndpointDocGenerator } from '../../../../../../common/endpoint/generate_data'; -import { composeHttpHandlerMocks } from '../../../../mock/endpoint/http_handler_mock_factory'; -import type { EndpointMetadataHttpMocksInterface } from '../../../../../management/pages/endpoint_hosts/mocks'; -import { endpointMetadataHttpMocks } from '../../../../../management/pages/endpoint_hosts/mocks'; -import type { ResponseActionsHttpMocksInterface } from '../../../../../management/mocks/response_actions_http_mocks'; -import { responseActionsHttpMocks } from '../../../../../management/mocks/response_actions_http_mocks'; +import { EndpointActionGenerator } from '../../../../../../../common/endpoint/data_generators/endpoint_action_generator'; +import { EndpointDocGenerator } from '../../../../../../../common/endpoint/generate_data'; +import { composeHttpHandlerMocks } from '../../../../../mock/endpoint/http_handler_mock_factory'; +import type { EndpointMetadataHttpMocksInterface } from '../../../../../../management/pages/endpoint_hosts/mocks'; +import { endpointMetadataHttpMocks } from '../../../../../../management/pages/endpoint_hosts/mocks'; +import type { ResponseActionsHttpMocksInterface } from '../../../../../../management/mocks/response_actions_http_mocks'; +import { responseActionsHttpMocks } from '../../../../../../management/mocks/response_actions_http_mocks'; import { waitFor, within, fireEvent } from '@testing-library/react'; -import { getEmptyValue } from '../../../empty_value'; +import { getEmptyValue } from '../../../../empty_value'; import { clone, set } from 'lodash'; type AgentStatusApiMocksInterface = EndpointMetadataHttpMocksInterface & diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/endpoint/endpoint_agent_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/endpoint/endpoint_agent_status.tsx similarity index 91% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status/endpoint/endpoint_agent_status.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/endpoint/endpoint_agent_status.tsx index 85568daa312b4..a2b6d869f9d2d 100644 --- a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/endpoint/endpoint_agent_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/endpoint/endpoint_agent_status.tsx @@ -9,14 +9,14 @@ import React, { memo, useMemo } from 'react'; import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; -import { DEFAULT_POLL_INTERVAL } from '../../../../../management/common/constants'; -import { HOST_STATUS_TO_BADGE_COLOR } from '../../../../../management/pages/endpoint_hosts/view/host_constants'; -import { getEmptyValue } from '../../../empty_value'; - -import { useGetEndpointPendingActionsSummary } from '../../../../../management/hooks/response_actions/use_get_endpoint_pending_actions_summary'; -import { useTestIdGenerator } from '../../../../../management/hooks/use_test_id_generator'; -import type { EndpointPendingActions, HostInfo } from '../../../../../../common/endpoint/types'; -import { useGetEndpointDetails } from '../../../../../management/hooks'; +import { DEFAULT_POLL_INTERVAL } from '../../../../../../management/common/constants'; +import { HOST_STATUS_TO_BADGE_COLOR } from '../../../../../../management/pages/endpoint_hosts/view/host_constants'; +import { getEmptyValue } from '../../../../empty_value'; + +import { useGetEndpointPendingActionsSummary } from '../../../../../../management/hooks/response_actions/use_get_endpoint_pending_actions_summary'; +import { useTestIdGenerator } from '../../../../../../management/hooks/use_test_id_generator'; +import type { EndpointPendingActions, HostInfo } from '../../../../../../../common/endpoint/types'; +import { useGetEndpointDetails } from '../../../../../../management/hooks'; import { getAgentStatusText } from '../../agent_status_text'; import { AgentResponseActionsStatus } from '../agent_response_action_status'; diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status/index.ts rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status/index.ts diff --git a/x-pack/plugins/security_solution/public/common/components/agents/agent_status_text.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status_text.ts similarity index 90% rename from x-pack/plugins/security_solution/public/common/components/agents/agent_status_text.ts rename to x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status_text.ts index 45ffd9a90ce93..ac0987e295283 100644 --- a/x-pack/plugins/security_solution/public/common/components/agents/agent_status_text.ts +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agents/agent_status_text.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { HostStatus } from '../../../../common/endpoint/types'; +import type { HostStatus } from '../../../../../common/endpoint/types'; export const getAgentStatusText = (hostStatus: HostStatus) => { return i18n.translate('xpack.securitySolution.endpoint.list.hostStatusValue', { diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/__mocks__/index.ts similarity index 78% rename from x-pack/plugins/security_solution/public/detections/components/endpoint_responder/index.ts rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/__mocks__/index.ts index 5581755690e92..98e117c7017e0 100644 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/__mocks__/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { useResponderActionItem } from './use_responder_action_item'; +export * from '../from_alerts/__mocks__'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/index.ts new file mode 100644 index 0000000000000..033cb24d79ac3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './use_host_isolation_action'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/use_host_isolation_action.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/use_host_isolation_action.tsx new file mode 100644 index 0000000000000..6bbe386ff176d --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/__mocks__/use_host_isolation_action.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AlertTableContextMenuItem } from '../../../../../../detections/components/alerts_table/types'; +import { ISOLATE_HOST } from '../translations'; + +const useHostIsolationActionMock = (): AlertTableContextMenuItem[] => { + return [ + { + key: 'isolate-host-action-item', + 'data-test-subj': 'isolate-host-action-item', + disabled: false, + onClick: jest.fn(), + name: ISOLATE_HOST, + }, + ]; +}; + +export { useHostIsolationActionMock as useHostIsolationAction }; diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.test.tsx similarity index 69% rename from x-pack/plugins/security_solution/public/detections/components/host_isolation/index.test.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.test.tsx index 6a357e232a59d..c3a37d9b03128 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.test.tsx @@ -8,8 +8,10 @@ import React from 'react'; import { renderReactTestingLibraryWithI18n as render } from '@kbn/test-jest-helpers'; import { HostIsolationPanel } from '.'; -import { useKibana as mockUseKibana } from '../../../common/lib/kibana/__mocks__'; +import { useKibana as mockUseKibana } from '../../../../lib/kibana/__mocks__'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { endpointAlertDataMock } from '../../../../mock/endpoint'; +import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; const queryClient = new QueryClient({ logger: { @@ -19,36 +21,40 @@ const queryClient = new QueryClient({ }, }); +jest.mock('../../../../experimental_features_service'); + const useKibanaMock = mockUseKibana as jest.Mock; -jest.mock('../../../common/lib/kibana'); +jest.mock('../../../../lib/kibana'); describe('HostIsolationPanel', () => { const renderWithContext = (Element: React.ReactElement) => render({Element}); + let cancelCallback: () => void; + let details: TimelineEventsDetailsItem[]; + beforeEach(() => { useKibanaMock.mockReturnValue({ ...mockUseKibana(), services: { ...mockUseKibana().services, notifications: { toasts: jest.fn() } }, }); + + cancelCallback = jest.fn(); + details = endpointAlertDataMock.generateEndpointAlertDetailsItemData(); }); - const details = [ - { - category: 'observer', - field: 'observer.serial_number', - values: ['expectedSentinelOneAgentId'], - originalValue: ['expectedSentinelOneAgentId'], - isObjectArray: false, - }, - { - category: 'crowdstrike', - field: 'crowdstrike.event.DeviceId', - values: ['expectedCrowdstrikeAgentId'], - originalValue: ['expectedCrowdstrikeAgentId'], - isObjectArray: false, - }, - ]; - const cancelCallback = jest.fn(); + it('should render warning callout if alert data host does not support response actions', () => { + const { getByTestId } = renderWithContext( + + ); + + expect(getByTestId('unsupportedAlertHost')).toHaveTextContent( + "The alert's host () does not support host isolation response actions." + ); + }); it('renders IsolateHost when isolateAction is "isolateHost"', () => { const { getByText } = renderWithContext( diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.tsx new file mode 100644 index 0000000000000..38e6ff1010d5c --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/host_isolation_panel.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiCallOut } from '@elastic/eui'; +import { getAlertDetailsFieldValue } from '../../../../lib/endpoint/utils/get_event_details_field_values'; +import { useCasesFromAlerts } from '../../../../../detections/containers/detection_engine/alerts/use_cases_from_alerts'; +import type { TimelineEventsDetailsItem } from '../../../../../../common/search_strategy'; +import { IsolateHost } from './isolate'; +import { UnisolateHost } from './unisolate'; +import { useAlertResponseActionsSupport } from '../../../../hooks/endpoint/use_alert_response_actions_support'; + +export const HostIsolationPanel = React.memo( + ({ + details, + cancelCallback, + successCallback, + isolateAction, + }: { + details: TimelineEventsDetailsItem[] | null; + cancelCallback: () => void; + successCallback?: () => void; + isolateAction: string; + }) => { + const { + isSupported: alertHostSupportsResponseActions, + details: { agentId, agentType, hostName }, + } = useAlertResponseActionsSupport(details); + + const alertId = useMemo( + () => getAlertDetailsFieldValue({ category: '_id', field: '_id' }, details), + [details] + ); + + const { casesInfo } = useCasesFromAlerts({ alertId }); + + const formProps: React.ComponentProps & + React.ComponentProps = useMemo(() => { + return { + endpointId: agentId, + hostName, + casesInfo, + agentType, + cancelCallback, + successCallback, + }; + }, [agentId, agentType, cancelCallback, casesInfo, hostName, successCallback]); + + if (!alertHostSupportsResponseActions) { + return ( + + + + ); + } + + return isolateAction === 'isolateHost' ? ( + + ) : ( + + ); + } +); + +HostIsolationPanel.displayName = 'HostIsolationContent'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/index.ts new file mode 100644 index 0000000000000..3ea62053d1ba9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './host_isolation_panel'; +export * from './use_host_isolation_action'; +export * from './translations'; diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/isolate.tsx similarity index 85% rename from x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/isolate.tsx index 37fa3ad4bfccc..df141abcba5e7 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/isolate.tsx @@ -8,15 +8,12 @@ import React, { useMemo, useState, useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; -import { useHostIsolation } from '../../containers/detection_engine/alerts/use_host_isolation'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { useHostIsolation } from './use_host_isolation'; import { CASES_ASSOCIATED_WITH_ALERT, RETURN_TO_ALERT_DETAILS } from './translations'; -import type { EndpointIsolatedFormProps } from '../../../common/components/endpoint/host_isolation'; -import { - EndpointIsolateForm, - ActionCompletionReturnButton, -} from '../../../common/components/endpoint/host_isolation'; -import type { CasesFromAlertsResponse } from '../../containers/detection_engine/alerts/types'; +import type { EndpointIsolatedFormProps } from '..'; +import { EndpointIsolateForm, ActionCompletionReturnButton } from '..'; +import type { CasesFromAlertsResponse } from '../../../../../detections/containers/detection_engine/alerts/types'; export const IsolateHost = React.memo( ({ diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/translations.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/translations.ts similarity index 100% rename from x-pack/plugins/security_solution/public/detections/components/host_isolation/translations.ts rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/translations.ts diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/unisolate.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/unisolate.tsx similarity index 85% rename from x-pack/plugins/security_solution/public/detections/components/host_isolation/unisolate.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/unisolate.tsx index 15c59da521579..171b0283a15c8 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/unisolate.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/unisolate.tsx @@ -8,15 +8,12 @@ import React, { useMemo, useState, useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; import { CASES_ASSOCIATED_WITH_ALERT, RETURN_TO_ALERT_DETAILS } from './translations'; -import type { EndpointIsolatedFormProps } from '../../../common/components/endpoint/host_isolation'; -import { - EndpointUnisolateForm, - ActionCompletionReturnButton, -} from '../../../common/components/endpoint/host_isolation'; -import { useHostUnisolation } from '../../containers/detection_engine/alerts/use_host_unisolation'; -import type { CasesFromAlertsResponse } from '../../containers/detection_engine/alerts/types'; +import type { EndpointIsolatedFormProps } from '..'; +import { EndpointUnisolateForm, ActionCompletionReturnButton } from '..'; +import { useHostUnisolation } from './use_host_unisolation'; +import type { CasesFromAlertsResponse } from '../../../../../detections/containers/detection_engine/alerts/types'; export const UnisolateHost = React.memo( ({ diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation.tsx similarity index 78% rename from x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation.tsx index 85b2bea5d2695..6964ee1a34308 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation.tsx @@ -6,10 +6,10 @@ */ import { useCallback, useState } from 'react'; -import type { ResponseActionAgentType } from '../../../../../common/endpoint/service/response_actions/constants'; -import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; -import { HOST_ISOLATION_FAILURE } from './translations'; -import { createHostIsolation } from './api'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { useAppToasts } from '../../../../hooks/use_app_toasts'; +import { HOST_ISOLATION_FAILURE } from '../../../../../detections/containers/detection_engine/alerts/translations'; +import { createHostIsolation } from '../../../../../detections/containers/detection_engine/alerts/api'; interface HostIsolationStatus { loading: boolean; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx new file mode 100644 index 0000000000000..5c459286fe11b --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FC, PropsWithChildren } from 'react'; +import React from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { useHostIsolationAction } from './use_host_isolation_action'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { + useAgentStatusHook, + useGetAgentStatus, + useGetSentinelOneAgentStatus, +} from '../../../../../management/hooks/agents/use_get_agent_status'; +import { useIsExperimentalFeatureEnabled } from '../../../../hooks/use_experimental_features'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { ExperimentalFeaturesService as ExperimentalFeaturesServiceMock } from '../../../../experimental_features_service'; +import { endpointAlertDataMock } from '../../../../mock/endpoint'; + +jest.mock('../../../../../management/hooks/agents/use_get_agent_status'); +jest.mock('../../../../hooks/use_experimental_features'); +jest.mock('../../../../experimental_features_service'); + +const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; +const useGetSentinelOneAgentStatusMock = useGetSentinelOneAgentStatus as jest.Mock; +const useGetAgentStatusMock = useGetAgentStatus as jest.Mock; +const useAgentStatusHookMock = useAgentStatusHook as jest.Mock; + +describe('useHostIsolationAction', () => { + const setFeatureFlags = (isEnabled: boolean = true): void => { + useIsExperimentalFeatureEnabledMock.mockReturnValue(isEnabled); + (ExperimentalFeaturesServiceMock.get as jest.Mock).mockReturnValue({ + responseActionsSentinelOneV1Enabled: isEnabled, + responseActionsCrowdstrikeManualHostIsolationEnabled: isEnabled, + }); + }; + + const createReactQueryWrapper = () => { + const queryClient = new QueryClient(); + const wrapper: FC> = ({ children }) => ( + {children} + ); + return wrapper; + }; + + it('should NOT return the menu item for Events', () => { + useAgentStatusHookMock.mockImplementation(() => { + return jest.fn(() => { + return { data: {} }; + }); + }); + setFeatureFlags(true); + const { result } = renderHook( + () => { + return useHostIsolationAction({ + closePopover: jest.fn(), + detailsData: endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo', { + 'kibana.alert.rule.uuid': undefined, + }), + isHostIsolationPanelOpen: false, + onAddIsolationStatusClick: jest.fn(), + }); + }, + { wrapper: createReactQueryWrapper() } + ); + + expect(result.current).toHaveLength(0); + }); + + // FIXME:PT refactor describe below - its not actually testing the component! Tests seem to be for `useAgentStatusHook()` + describe.each([ + ['useGetSentinelOneAgentStatus', useGetSentinelOneAgentStatusMock], + ['useGetAgentStatus', useGetAgentStatusMock], + ])('works with %s hook', (name, hook) => { + const render = (agentTypeAlert: ResponseActionAgentType) => + renderHook( + () => + useHostIsolationAction({ + closePopover: jest.fn(), + detailsData: + endpointAlertDataMock.generateAlertDetailsItemDataForAgentType(agentTypeAlert), + isHostIsolationPanelOpen: false, + onAddIsolationStatusClick: jest.fn(), + }), + { + wrapper: createReactQueryWrapper(), + } + ); + + beforeEach(() => { + useAgentStatusHookMock.mockImplementation(() => hook); + setFeatureFlags(true); + }); + + afterEach(() => { + jest.clearAllMocks(); + (ExperimentalFeaturesServiceMock.get as jest.Mock).mockReset(); + }); + + it(`${name} is invoked as 'enabled' when SentinelOne alert and FF enabled`, () => { + render('sentinel_one'); + + expect(hook).toHaveBeenCalledWith(['abfe4a35-d5b4-42a0-a539-bd054c791769'], 'sentinel_one', { + enabled: true, + }); + }); + it(`${name} is invoked as 'enabled' when Crowdstrike alert and FF enabled`, () => { + render('crowdstrike'); + + expect(hook).toHaveBeenCalledWith(['abfe4a35-d5b4-42a0-a539-bd054c791769'], 'crowdstrike', { + enabled: true, + }); + }); + + it(`${name} is invoked as 'disabled' when SentinelOne alert and FF disabled`, () => { + setFeatureFlags(false); + render('sentinel_one'); + + expect(hook).toHaveBeenCalledWith(['abfe4a35-d5b4-42a0-a539-bd054c791769'], 'sentinel_one', { + enabled: false, + }); + }); + + it(`${name} is invoked as 'disabled' when Crowdstrike alert and FF disabled`, () => { + setFeatureFlags(false); + render('crowdstrike'); + + expect(hook).toHaveBeenCalledWith(['abfe4a35-d5b4-42a0-a539-bd054c791769'], 'crowdstrike', { + enabled: false, + }); + }); + + it(`${name} is invoked as 'disabled' when endpoint alert`, () => { + render('endpoint'); + + expect(hook).toHaveBeenCalledWith(['abfe4a35-d5b4-42a0-a539-bd054c791769'], 'endpoint', { + enabled: false, + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.tsx new file mode 100644 index 0000000000000..42f31ba946887 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.tsx @@ -0,0 +1,175 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { useCallback, useMemo } from 'react'; +import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { + HOST_ENDPOINT_UNENROLLED_TOOLTIP, + LOADING_ENDPOINT_DATA_TOOLTIP, + NOT_FROM_ENDPOINT_HOST_TOOLTIP, +} from '../../responder'; +import { useAlertResponseActionsSupport } from '../../../../hooks/endpoint/use_alert_response_actions_support'; +import { useIsExperimentalFeatureEnabled } from '../../../../hooks/use_experimental_features'; +import type { AgentStatusInfo } from '../../../../../../common/endpoint/types'; +import { HostStatus } from '../../../../../../common/endpoint/types'; +import { useEndpointHostIsolationStatus } from './use_host_isolation_status'; +import { ISOLATE_HOST, UNISOLATE_HOST } from './translations'; +import { useUserPrivileges } from '../../../user_privileges'; +import type { AlertTableContextMenuItem } from '../../../../../detections/components/alerts_table/types'; +import { useAgentStatusHook } from '../../../../../management/hooks/agents/use_get_agent_status'; + +interface UseHostIsolationActionProps { + closePopover: () => void; + detailsData: TimelineEventsDetailsItem[] | null; + isHostIsolationPanelOpen: boolean; + onAddIsolationStatusClick: (action: 'isolateHost' | 'unisolateHost') => void; +} + +export const useHostIsolationAction = ({ + closePopover, + detailsData, + isHostIsolationPanelOpen, + onAddIsolationStatusClick, +}: UseHostIsolationActionProps): AlertTableContextMenuItem[] => { + const { + isSupported: hostSupportsResponseActions, + isAlert, + unsupportedReason, + details: { + agentType, + agentId, + agentSupport: { isolate: isolationSupported }, + }, + } = useAlertResponseActionsSupport(detailsData); + const agentStatusClientEnabled = useIsExperimentalFeatureEnabled('agentStatusClientEnabled'); + const useAgentStatus = useAgentStatusHook(); + const { canIsolateHost, canUnIsolateHost } = useUserPrivileges().endpointPrivileges; + + const isEndpointAgent = useMemo(() => { + return agentType === 'endpoint'; + }, [agentType]); + + const { + loading: loadingHostIsolationStatus, + isIsolated, + agentStatus, + capabilities, + } = useEndpointHostIsolationStatus({ + agentId, + agentType, + }); + + const { data: externalAgentData } = useAgentStatus([agentId], agentType, { + enabled: hostSupportsResponseActions && !isEndpointAgent, + }); + + const externalAgentStatus = externalAgentData?.[agentId]; + + const isHostIsolated = useMemo((): boolean => { + if (!isEndpointAgent) { + return Boolean(externalAgentStatus?.isolated); + } + + return isIsolated; + }, [isEndpointAgent, isIsolated, externalAgentStatus?.isolated]); + + const doesHostSupportIsolation = useMemo(() => { + // With Elastic Defend Endpoint, we check that the actual `endpoint` agent on + // this host reported that capability + if (agentType === 'endpoint') { + return capabilities.includes('isolation'); + } + + return Boolean(externalAgentStatus?.found && isolationSupported); + }, [agentType, externalAgentStatus?.found, isolationSupported, capabilities]); + + const isolateHostHandler = useCallback(() => { + closePopover(); + if (!isHostIsolated) { + onAddIsolationStatusClick('isolateHost'); + } else { + onAddIsolationStatusClick('unisolateHost'); + } + }, [closePopover, isHostIsolated, onAddIsolationStatusClick]); + + const isHostAgentUnEnrolled = useMemo(() => { + if (!hostSupportsResponseActions) { + return true; + } + + if (isEndpointAgent) { + return agentStatus === HostStatus.UNENROLLED; + } + + // NON-Endpoint agent types + // 8.15 use FF for computing if action is enabled + if (agentStatusClientEnabled) { + return externalAgentStatus?.status === HostStatus.UNENROLLED; + } + + // else use the old way + if (!externalAgentStatus) { + return true; + } + + const { isUninstalled, isPendingUninstall } = externalAgentStatus as AgentStatusInfo[string]; + + return isUninstalled || isPendingUninstall; + }, [ + hostSupportsResponseActions, + isEndpointAgent, + agentStatusClientEnabled, + externalAgentStatus, + agentStatus, + ]); + + return useMemo(() => { + // If not an Alert OR user has no Authz, then don't show the menu item at all + if (!isAlert || (isHostIsolated && !canUnIsolateHost) || !canIsolateHost) { + return []; + } + + const menuItem: AlertTableContextMenuItem = { + key: 'isolate-host-action-item', + 'data-test-subj': 'isolate-host-action-item', + disabled: isHostAgentUnEnrolled || isHostIsolationPanelOpen, + onClick: isolateHostHandler, + name: isHostIsolated ? UNISOLATE_HOST : ISOLATE_HOST, + }; + + // Determine if menu item should be disabled + if (!doesHostSupportIsolation) { + menuItem.disabled = true; + // If we were able to calculate the agentType and we have a reason why the host is does not + // support response actions, then show that as the tooltip. Else, just show the normal "enroll" message + menuItem.toolTipContent = + agentType && unsupportedReason ? unsupportedReason : NOT_FROM_ENDPOINT_HOST_TOOLTIP; + } else if (isEndpointAgent && loadingHostIsolationStatus) { + menuItem.disabled = true; + menuItem.toolTipContent = LOADING_ENDPOINT_DATA_TOOLTIP; + } else if (isHostAgentUnEnrolled) { + menuItem.disabled = true; + menuItem.toolTipContent = isEndpointAgent + ? HOST_ENDPOINT_UNENROLLED_TOOLTIP + : NOT_FROM_ENDPOINT_HOST_TOOLTIP; + } + + return [menuItem]; + }, [ + isAlert, + isHostIsolated, + canUnIsolateHost, + canIsolateHost, + isHostAgentUnEnrolled, + isHostIsolationPanelOpen, + isolateHostHandler, + doesHostSupportIsolation, + isEndpointAgent, + loadingHostIsolationStatus, + agentType, + unsupportedReason, + ]); +}; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_status.tsx similarity index 83% rename from x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_status.tsx index 0646a9904e939..825cff88ab95e 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_status.tsx @@ -7,11 +7,11 @@ import { isEmpty } from 'lodash'; import { useEffect, useState } from 'react'; -import type { ResponseActionAgentType } from '../../../../../common/endpoint/service/response_actions/constants'; -import { getHostMetadata } from './api'; -import { fetchPendingActionsByAgentId } from '../../../../common/lib/endpoint_pending_actions'; -import { isEndpointHostIsolated } from '../../../../common/utils/validators'; -import { HostStatus } from '../../../../../common/endpoint/types'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { getHostMetadata } from '../../../../../detections/containers/detection_engine/alerts/api'; +import { fetchPendingActionsByAgentId } from '../../../../lib/endpoint/endpoint_pending_actions'; +import { isEndpointHostIsolated } from '../../../../utils/validators'; +import { HostStatus } from '../../../../../../common/endpoint/types'; interface HostIsolationStatusResponse { loading: boolean; @@ -22,8 +22,9 @@ interface HostIsolationStatusResponse { pendingUnisolation: number; } -/* - * Retrieves the current isolation status of a host and the agent/host status */ +/** + * Retrieves the current isolation status of a host and the agent/host status + */ export const useEndpointHostIsolationStatus = ({ agentId, agentType, @@ -79,16 +80,15 @@ export const useEndpointHostIsolationStatus = ({ } } catch (error) { // silently catch non-user initiated error - return; - } - - if (isMounted) { - setLoading(false); } }; if (!isEmpty(agentId) && agentType === 'endpoint') { - fetchData(); + fetchData().finally(() => { + if (isMounted) { + setLoading(false); + } + }); } return () => { // updates to show component is unmounted diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_unisolation.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_unisolation.tsx similarity index 77% rename from x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_unisolation.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_unisolation.tsx index 47c09186f7cba..1cd0d7fe3b886 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_unisolation.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_unisolation.tsx @@ -6,10 +6,10 @@ */ import { useCallback, useState } from 'react'; -import type { ResponseActionAgentType } from '../../../../../common/endpoint/service/response_actions/constants'; -import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; -import { HOST_ISOLATION_FAILURE } from './translations'; -import { createHostUnIsolation } from './api'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { useAppToasts } from '../../../../hooks/use_app_toasts'; +import { HOST_ISOLATION_FAILURE } from '../../../../../detections/containers/detection_engine/alerts/translations'; +import { createHostUnIsolation } from '../../../../../detections/containers/detection_engine/alerts/api'; interface HostUnisolationStatus { loading: boolean; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_cases/endpoint_host_isolation_cases_context.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_cases/endpoint_host_isolation_cases_context.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_cases/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_cases/index.ts new file mode 100644 index 0000000000000..930e3d362683a --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_cases/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './endpoint_host_isolation_cases_context'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/index.ts index 41763a6e88d37..077bb416c800f 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/index.ts @@ -9,3 +9,5 @@ export * from './isolate_success'; export * from './isolate_form'; export * from './unisolate_form'; export * from './action_completion_return_button'; +export * from './from_alerts'; +export * from './from_cases'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/index.ts new file mode 100644 index 0000000000000..49ad6c8bfd9d2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './host_isolation'; +export * from './responder'; +export * from './link_to_app'; +export * from './route_capture'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/__mocks__/index.ts new file mode 100644 index 0000000000000..98e117c7017e0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/__mocks__/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from '../from_alerts/__mocks__'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/index.ts new file mode 100644 index 0000000000000..9f070ce76a53d --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './use_responder_action_data'; +export * from './use_responder_action_item'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_data.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_data.ts new file mode 100644 index 0000000000000..c84c5ea9dafbd --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_data.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ResponderActionData, UseWithResponderActionDataFromAlertProps } from '../../..'; + +const useWithResponderActionDataFromAlertMock = ( + options: UseWithResponderActionDataFromAlertProps +): ResponderActionData => { + return { + handleResponseActionsClick: jest.fn(() => { + if (options.onClick) { + options.onClick(); + } + }), + isDisabled: false, + tooltip: null, + }; +}; + +export { useWithResponderActionDataFromAlertMock as useWithResponderActionDataFromAlert }; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_item.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_item.tsx new file mode 100644 index 0000000000000..bdeed284fa5ed --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/__mocks__/use_responder_action_item.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AlertTableContextMenuItem } from '../../../../../../detections/components/alerts_table/types'; + +const useResponderActionItemMock = (): AlertTableContextMenuItem[] => { + return [ + { + key: 'endpointResponseActions-action-item', + 'data-test-subj': 'endpointResponseActions-action-item', + disabled: false, + toolTipContent: undefined, + size: 's', + onClick: jest.fn(), + name: 'Respond', + }, + ]; +}; + +export { useResponderActionItemMock as useResponderActionItem }; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/index.ts new file mode 100644 index 0000000000000..2f39f582e93fc --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './responder_action_button'; +export * from './use_responder_action_item'; +export * from './use_responder_action_data'; +export * from './translations'; diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/responder_action_button.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/responder_action_button.tsx similarity index 76% rename from x-pack/plugins/security_solution/public/detections/components/endpoint_responder/responder_action_button.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/responder_action_button.tsx index cb5876f27dd67..5d3aba47c2184 100644 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/responder_action_button.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/responder_action_button.tsx @@ -8,18 +8,15 @@ import { EuiButton, EuiToolTip } from '@elastic/eui'; import React, { memo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { - type ResponderContextMenuItemProps, - useResponderActionData, -} from './use_responder_action_data'; -import { useUserPrivileges } from '../../../common/components/user_privileges'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { useResponderActionData } from './use_responder_action_data'; +import { useUserPrivileges } from '../../../user_privileges'; -export const ResponderActionButton = memo( - ({ agentType, endpointId, onClick }) => { +export const ResponderActionButton = memo<{ agentId: string; agentType: ResponseActionAgentType }>( + ({ agentType, agentId }) => { const { handleResponseActionsClick, isDisabled, tooltip } = useResponderActionData({ agentType, - endpointId, - onClick, + agentId, }); const endpointPrivileges = useUserPrivileges().endpointPrivileges; diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/translations.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/translations.ts similarity index 59% rename from x-pack/plugins/security_solution/public/detections/components/endpoint_responder/translations.ts rename to x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/translations.ts index 52dd93cc5c7cc..3df858b9673f1 100644 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/translations.ts @@ -6,8 +6,6 @@ */ import { i18n } from '@kbn/i18n'; -import { CROWDSTRIKE_AGENT_ID_FIELD } from '../../../common/utils/crowdstrike_alert_check'; -import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../common/utils/sentinelone_alert_check'; export const NOT_FROM_ENDPOINT_HOST_TOOLTIP = i18n.translate( 'xpack.securitySolution.endpoint.detections.takeAction.responseActionConsole.notSupportedTooltip', @@ -27,22 +25,3 @@ export const METADATA_API_ERROR_TOOLTIP = i18n.translate( 'xpack.securitySolution.endpoint.detections.takeAction.responseActionConsole.generalMetadataErrorTooltip', { defaultMessage: 'Failed to retrieve Endpoint metadata' } ); - -export const SENTINEL_ONE_AGENT_ID_PROPERTY_MISSING = i18n.translate( - 'xpack.securitySolution.endpoint.detections.takeAction.responseActionConsole.missingSentinelOneAgentId', - { - defaultMessage: 'Event data missing SentinelOne agent identifier ({field})', - values: { - field: SENTINEL_ONE_AGENT_ID_FIELD, - }, - } -); -export const CROWDSTRIKE_AGENT_ID_PROPERTY_MISSING = i18n.translate( - 'xpack.securitySolution.endpoint.detections.takeAction.responseActionConsole.missingCrowdstrikeAgentId', - { - defaultMessage: 'Event data missing Crowdstrike agent identifier ({field})', - values: { - field: CROWDSTRIKE_AGENT_ID_FIELD, - }, - } -); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts new file mode 100644 index 0000000000000..89ad874726d91 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts @@ -0,0 +1,283 @@ +/* + * Copyright 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 { + UseWithResponderActionDataFromAlertProps, + ResponderActionData, + UseResponderActionDataProps, +} from './use_responder_action_data'; +import { + useResponderActionData, + useWithResponderActionDataFromAlert, +} from './use_responder_action_data'; +import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { + HOST_ENDPOINT_UNENROLLED_TOOLTIP, + LOADING_ENDPOINT_DATA_TOOLTIP, + METADATA_API_ERROR_TOOLTIP, + NOT_FROM_ENDPOINT_HOST_TOOLTIP, +} from './translations'; +import type { AppContextTestRender } from '../../../../mock/endpoint'; +import { createAppRootMockRenderer, endpointAlertDataMock } from '../../../../mock/endpoint'; +import { HOST_METADATA_LIST_ROUTE } from '../../../../../../common/endpoint/constants'; +import { endpointMetadataHttpMocks } from '../../../../../management/pages/endpoint_hosts/mocks'; +import type { RenderHookResult } from '@testing-library/react-hooks/src/types'; +import { createHttpFetchError } from '@kbn/core-http-browser-mocks'; +import { HostStatus } from '../../../../../../common/endpoint/types'; +import { + RESPONSE_ACTION_AGENT_TYPE, + RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD, +} from '../../../../../../common/endpoint/service/response_actions/constants'; +import { getAgentTypeName } from '../../../../translations'; +import { ALERT_EVENT_DATA_MISSING_AGENT_ID_FIELD } from '../../../../hooks/endpoint/use_alert_response_actions_support'; + +describe('use responder action data hooks', () => { + let appContextMock: AppContextTestRender; + let onClickMock: UseWithResponderActionDataFromAlertProps['onClick']; + + const getExpectedResponderActionData = ( + overrides: Partial = {} + ): ResponderActionData => { + return { + isDisabled: false, + tooltip: undefined, + handleResponseActionsClick: expect.any(Function), + ...overrides, + }; + }; + + beforeEach(() => { + appContextMock = createAppRootMockRenderer(); + onClickMock = jest.fn(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('useWithResponderActionDataFromAlert() hook', () => { + let renderHook: () => RenderHookResult< + UseWithResponderActionDataFromAlertProps, + ResponderActionData + >; + let alertDetailItemData: TimelineEventsDetailsItem[]; + + beforeEach(() => { + renderHook = () => { + return appContextMock.renderHook< + UseWithResponderActionDataFromAlertProps, + ResponderActionData + >(() => + useWithResponderActionDataFromAlert({ + eventData: alertDetailItemData, + onClick: onClickMock, + }) + ); + }; + }); + + describe('Common behaviours', () => { + it('should show action as disabled if agent does not support response actions', () => { + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo'); + + expect(renderHook().result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: NOT_FROM_ENDPOINT_HOST_TOOLTIP, + }) + ); + }); + + it('should call `onClick()` function prop when is pass to the hook', () => { + alertDetailItemData = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); + const { result } = renderHook(); + result.current.handleResponseActionsClick(); + + expect(onClickMock).toHaveBeenCalled(); + }); + + it('should NOT call `onClick` if the action is disabled', () => { + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo'); + const { result } = renderHook(); + result.current.handleResponseActionsClick(); + + expect(onClickMock).not.toHaveBeenCalled(); + }); + }); + + describe('and agentType is NOT Endpoint', () => { + beforeEach(() => { + alertDetailItemData = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); + }); + + it('should show action when agentType is supported', () => { + expect(renderHook().result.current).toEqual(getExpectedResponderActionData()); + }); + + it('should NOT call the endpoint host metadata api', () => { + renderHook(); + const wasMetadataApiCalled = appContextMock.coreStart.http.get.mock.calls.some(([path]) => { + return (path as unknown as string).includes(HOST_METADATA_LIST_ROUTE); + }); + + expect(wasMetadataApiCalled).toBe(false); + }); + + it.each([...RESPONSE_ACTION_AGENT_TYPE])( + 'should show action disabled with tooltip for %s if agent id field is missing', + (agentType) => { + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType( + agentType, + { + [RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD[agentType]]: undefined, + } + ); + + expect(renderHook().result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: ALERT_EVENT_DATA_MISSING_AGENT_ID_FIELD( + getAgentTypeName(agentType), + RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD[agentType] + ), + }) + ); + } + ); + }); + + describe('and agentType IS Endpoint', () => { + let metadataApiMocks: ReturnType; + + beforeEach(() => { + alertDetailItemData = endpointAlertDataMock.generateEndpointAlertDetailsItemData(); + metadataApiMocks = endpointMetadataHttpMocks(appContextMock.coreStart.http); + }); + + it('should show action disabled with tooltip while retrieving host metadata', () => { + expect(renderHook().result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: LOADING_ENDPOINT_DATA_TOOLTIP, + }) + ); + }); + + it('should show action enabled if host metadata was retrieved and host is enrolled', async () => { + const { result, waitForValueToChange } = renderHook(); + await waitForValueToChange(() => result.current.isDisabled); + + expect(result.current).toEqual(getExpectedResponderActionData()); + }); + + it('should show action disabled if host was not found', async () => { + metadataApiMocks.responseProvider.metadataDetails.mockImplementation(() => { + throw createHttpFetchError('Not found', undefined, undefined, undefined, { + statusCode: 404, + }); + }); + const { result, waitForValueToChange } = renderHook(); + await waitForValueToChange(() => result.current.tooltip); + + expect(result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: NOT_FROM_ENDPOINT_HOST_TOOLTIP, + }) + ); + }); + + it('should show action as disabled with tooltip when host is found, but has a status of unenrolled', async () => { + const hostMetadata = { + ...metadataApiMocks.responseProvider.metadataDetails(), + host_status: HostStatus.UNENROLLED, + }; + metadataApiMocks.responseProvider.metadataDetails.mockReturnValue(hostMetadata); + + const { result, waitForValueToChange } = renderHook(); + await waitForValueToChange(() => result.current.tooltip); + + expect(result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: HOST_ENDPOINT_UNENROLLED_TOOLTIP, + }) + ); + }); + + it('should show action disabled if a metadata API error was encountered', async () => { + metadataApiMocks.responseProvider.metadataDetails.mockImplementation(() => { + throw createHttpFetchError('Server error', undefined, undefined, undefined, { + statusCode: 500, + }); + }); + const { result, waitForValueToChange } = renderHook(); + await waitForValueToChange(() => result.current.tooltip); + + expect(result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: METADATA_API_ERROR_TOOLTIP, + }) + ); + }); + }); + }); + + describe('useResponderActionData() hook', () => { + let hookProps: UseResponderActionDataProps; + let renderHook: () => RenderHookResult; + + beforeEach(() => { + endpointMetadataHttpMocks(appContextMock.coreStart.http); + hookProps = { + agentId: 'agent-123', + agentType: 'endpoint', + onClick: onClickMock, + }; + renderHook = () => { + return appContextMock.renderHook(() => + useResponderActionData(hookProps) + ); + }; + }); + + it('should show action enabled when agentType is Endpoint and host is enabled', async () => { + const { result, waitForValueToChange } = renderHook(); + await waitForValueToChange(() => result.current.isDisabled); + + expect(result.current).toEqual(getExpectedResponderActionData()); + }); + + it('should show action disabled if agent type is not Endpoint', () => { + hookProps.agentType = 'crowdstrike'; + + expect(renderHook().result.current).toEqual( + getExpectedResponderActionData({ + isDisabled: true, + tooltip: NOT_FROM_ENDPOINT_HOST_TOOLTIP, + }) + ); + }); + + it('should call `onClick` prop when action is enabled', async () => { + const { result, waitForValueToChange } = renderHook(); + await waitForValueToChange(() => result.current.isDisabled); + result.current.handleResponseActionsClick(); + + expect(onClickMock).toHaveBeenCalled(); + }); + + it('should not call `onCLick` prop when action is disabled', () => { + hookProps.agentType = 'sentinel_one'; + const { result } = renderHook(); + result.current.handleResponseActionsClick(); + + expect(onClickMock).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.ts new file mode 100644 index 0000000000000..266425dd452da --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.ts @@ -0,0 +1,271 @@ +/* + * Copyright 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 { ReactNode } from 'react'; +import { useCallback, useMemo } from 'react'; +import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { useAlertResponseActionsSupport } from '../../../../hooks/endpoint/use_alert_response_actions_support'; +import type { + EndpointCapabilities, + ResponseActionAgentType, +} from '../../../../../../common/endpoint/service/response_actions/constants'; +import { useGetEndpointDetails, useWithShowResponder } from '../../../../../management/hooks'; +import { HostStatus } from '../../../../../../common/endpoint/types'; +import { + HOST_ENDPOINT_UNENROLLED_TOOLTIP, + LOADING_ENDPOINT_DATA_TOOLTIP, + METADATA_API_ERROR_TOOLTIP, + NOT_FROM_ENDPOINT_HOST_TOOLTIP, +} from './translations'; + +export interface UseWithResponderActionDataFromAlertProps { + eventData: TimelineEventsDetailsItem[] | null; + onClick?: () => void; +} + +export interface ResponderActionData { + handleResponseActionsClick: () => void; + isDisabled: boolean; + tooltip: ReactNode; +} + +/** + * This hook is used to get the data needed to show the context menu items for the responder + * actions using Alert data. + * + * NOTE: If wanting to get teh same type of response but don't have Alert + * data, use `useResponderActionData()` instead + * + * @param onClick the callback to handle the click event + * @param eventData the event data, exists only when agentType !== 'endpoint' + * @returns an object with the data needed to show the context menu item + */ +export const useWithResponderActionDataFromAlert = ({ + eventData = [], + onClick, +}: UseWithResponderActionDataFromAlertProps): ResponderActionData => { + const { + isSupported: hostSupportsResponseActions, + unsupportedReason, + details: { agentType, agentId, platform, hostName }, + } = useAlertResponseActionsSupport(eventData); + + const isEndpointHost = agentType === 'endpoint'; + + const endpointHostData = useResponderDataForEndpointHost( + agentId, + hostSupportsResponseActions && isEndpointHost + ); + const showResponseActionsConsole = useWithShowResponder(); + + const [isDisabled, tooltip]: [disabled: boolean, tooltip: ReactNode] = useMemo(() => { + if (!hostSupportsResponseActions) { + return [ + true, + agentType && unsupportedReason ? unsupportedReason : NOT_FROM_ENDPOINT_HOST_TOOLTIP, + ]; + } + + if (isEndpointHost) { + return [endpointHostData.isDisabled, endpointHostData.tooltip]; + } + + return [false, undefined]; + }, [ + hostSupportsResponseActions, + isEndpointHost, + agentType, + unsupportedReason, + endpointHostData.isDisabled, + endpointHostData.tooltip, + ]); + + const handleResponseActionsClick = useCallback(() => { + if (!isDisabled) { + showResponseActionsConsole({ + agentId, + agentType, + hostName, + platform, + capabilities: isEndpointHost ? endpointHostData.capabilities : [], + }); + + if (onClick) { + onClick(); + } + } + }, [ + isDisabled, + showResponseActionsConsole, + agentId, + agentType, + hostName, + platform, + isEndpointHost, + endpointHostData.capabilities, + onClick, + ]); + + return { + handleResponseActionsClick, + isDisabled, + tooltip, + }; +}; + +type ResponderDataForEndpointHost = Omit & { + capabilities: EndpointCapabilities[]; + hostName: string; + platform: string; +}; + +/** + * Hook to specifically for the responder data for Elastic Defend endpoints + * @param endpointAgentId + * @param enabled + * + * @private + */ +const useResponderDataForEndpointHost = ( + endpointAgentId: string, + enabled: boolean = true +): ResponderDataForEndpointHost => { + // FIXME:PT is this the correct API to call? or should we call the agent status api instead + + const { + data: endpointHostInfo, + isFetching, + error, + } = useGetEndpointDetails(endpointAgentId, { + enabled, + }); + + return useMemo(() => { + const response: ResponderDataForEndpointHost = { + isDisabled: false, + tooltip: undefined, + capabilities: [], + hostName: '', + platform: '', + }; + + if (!enabled) { + response.isDisabled = true; + return response; + } + + if (isFetching) { + response.isDisabled = true; + response.tooltip = LOADING_ENDPOINT_DATA_TOOLTIP; + return response; + } + + // if we got an error, and it's a 404, it means the endpoint is not from the endpoint host + if (error && error.body?.statusCode === 404) { + response.isDisabled = true; + response.tooltip = NOT_FROM_ENDPOINT_HOST_TOOLTIP; + return response; + } + + // if we got an error and, + // it's a 400 with unenrolled in the error message (alerts can exist for endpoint that are no longer around) + // or, + // the Host status is `unenrolled` + if ( + (error && error.body?.statusCode === 400 && error.body?.message.includes('unenrolled')) || + endpointHostInfo?.host_status === HostStatus.UNENROLLED + ) { + response.isDisabled = true; + response.tooltip = HOST_ENDPOINT_UNENROLLED_TOOLTIP; + return response; + } + + // return general error tooltip + if (error) { + response.isDisabled = true; + response.tooltip = METADATA_API_ERROR_TOOLTIP; + } + + response.capabilities = (endpointHostInfo?.metadata.Endpoint.capabilities ?? + []) as EndpointCapabilities[]; + response.hostName = endpointHostInfo?.metadata.host.name ?? ''; + response.platform = endpointHostInfo?.metadata.host.os.name.toLowerCase() ?? ''; + + return response; + }, [ + enabled, + isFetching, + error, + endpointHostInfo?.host_status, + endpointHostInfo?.metadata.Endpoint.capabilities, + endpointHostInfo?.metadata.host.name, + endpointHostInfo?.metadata.host.os.name, + ]); +}; + +export interface UseResponderActionDataProps { + agentId: string; + agentType: ResponseActionAgentType; + onClick?: () => void; +} + +/** + * Returns the data necessary to render a Responder action item (ex. menu item) when only the + * `agentId` and `agentType` is available (ex. when showing the `Respond` button on the Host + * details page of SIEM + * @param onClick + * @param agentId + * @param agentType + */ +export const useResponderActionData = ({ + onClick, + agentId, + agentType, +}: UseResponderActionDataProps): ResponderActionData => { + const isEndpointHost = agentType === 'endpoint'; + + const showResponseActionsConsole = useWithShowResponder(); + const { tooltip, isDisabled, capabilities, hostName, platform } = useResponderDataForEndpointHost( + agentId, + isEndpointHost + ); + + // TODO:PT add support for other agent types once we add the `Respond` button to the Host details page in SIEM + + const handleResponseActionsClick = useCallback(() => { + if (!isDisabled) { + showResponseActionsConsole({ + agentId, + agentType, + hostName, + platform, + capabilities: isEndpointHost ? capabilities : [], + }); + + if (onClick) { + onClick(); + } + } + }, [ + isDisabled, + showResponseActionsConsole, + agentId, + agentType, + hostName, + platform, + isEndpointHost, + capabilities, + onClick, + ]); + + return useMemo(() => { + return { + isDisabled: isEndpointHost ? isDisabled : true, + tooltip: isEndpointHost ? tooltip : NOT_FROM_ENDPOINT_HOST_TOOLTIP, + handleResponseActionsClick, + }; + }, [handleResponseActionsClick, isDisabled, isEndpointHost, tooltip]); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.test.tsx new file mode 100644 index 0000000000000..b499f8a795fa9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.test.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useResponderActionItem } from './use_responder_action_item'; +import { useUserPrivileges as _useUserPrivileges } from '../../../user_privileges'; +import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import type { AppContextTestRender } from '../../../../mock/endpoint'; +import { createAppRootMockRenderer } from '../../../../mock/endpoint'; +import { endpointAlertDataMock } from '../../../../mock/endpoint/endpoint_alert_data_mock'; + +jest.mock('../../../user_privileges'); +jest.mock('./use_responder_action_data'); + +const useUserPrivilegesMock = _useUserPrivileges as jest.Mock; + +describe('useResponderActionItem', () => { + let alertDetailItemData: TimelineEventsDetailsItem[]; + let renderHook: () => ReturnType; + + beforeEach(() => { + const appContextMock = createAppRootMockRenderer(); + + // This is on purpose - an alert for an unsupported agent type. The menu item should always be + // visible as long as the user has authz to it. In this case it will be disabled. + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo'); + + renderHook = () => + appContextMock.renderHook(() => useResponderActionItem(alertDetailItemData, () => {})); + + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: { loading: false, canAccessResponseConsole: true }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return Respond action menu item if user has Authz', () => { + expect(renderHook().result.current).toHaveLength(1); + }); + + it('should NOT return the Respond action menu item if user is not Authorized', () => { + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: { loading: false, canAccessResponseConsole: false }, + }); + expect(renderHook().result.current).toHaveLength(0); + }); + + it('should NOT return the Respond action menu item for Events', () => { + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo', { + 'kibana.alert.rule.uuid': undefined, + }); + + expect(renderHook().result.current).toHaveLength(0); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.tsx similarity index 52% rename from x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx rename to x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.tsx index 57b51c23f2032..6ccc6b4447907 100644 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_item.tsx @@ -8,14 +8,10 @@ import React, { useMemo } from 'react'; import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; -import { isAlertFromCrowdstrikeEvent } from '../../../common/utils/crowdstrike_alert_check'; -import { isAlertFromSentinelOneEvent } from '../../../common/utils/sentinelone_alert_check'; -import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; -import { useUserPrivileges } from '../../../common/components/user_privileges'; -import { isTimelineEventItemAnAlert } from '../../../common/utils/endpoint_alert_check'; -import { getFieldValue } from '../host_isolation/helpers'; -import type { AlertTableContextMenuItem } from '../alerts_table/types'; -import { useResponderActionData } from './use_responder_action_data'; +import { useAlertResponseActionsSupport } from '../../../../hooks/endpoint/use_alert_response_actions_support'; +import { useUserPrivileges } from '../../../user_privileges'; +import type { AlertTableContextMenuItem } from '../../../../../detections/components/alerts_table/types'; +import { useWithResponderActionDataFromAlert } from './use_responder_action_data'; export const useResponderActionItem = ( eventDetailsData: TimelineEventsDetailsItem[] | null, @@ -23,36 +19,10 @@ export const useResponderActionItem = ( ): AlertTableContextMenuItem[] => { const { loading: isAuthzLoading, canAccessResponseConsole } = useUserPrivileges().endpointPrivileges; - - const isAlert = useMemo(() => { - return isTimelineEventItemAnAlert(eventDetailsData || []); - }, [eventDetailsData]); - - const endpointId: string = useMemo( - () => getFieldValue({ category: 'agent', field: 'agent.id' }, eventDetailsData), - [eventDetailsData] - ); - - const agentType: ResponseActionAgentType = useMemo(() => { - if (!eventDetailsData) { - return 'endpoint'; - } - - if (isAlertFromSentinelOneEvent({ data: eventDetailsData })) { - return 'sentinel_one'; - } - if (isAlertFromCrowdstrikeEvent({ data: eventDetailsData })) { - return 'crowdstrike'; - } - - return 'endpoint'; - }, [eventDetailsData]); - - const { handleResponseActionsClick, isDisabled, tooltip } = useResponderActionData({ - endpointId, + const { isAlert } = useAlertResponseActionsSupport(eventDetailsData); + const { handleResponseActionsClick, isDisabled, tooltip } = useWithResponderActionDataFromAlert({ onClick, - agentType, - eventData: agentType !== 'endpoint' ? eventDetailsData : null, + eventData: eventDetailsData, }); return useMemo(() => { diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/index.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/index.ts new file mode 100644 index 0000000000000..c030b4780dd26 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './from_alerts'; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts index 60bc2b7f3ce31..fc793df1025e7 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts @@ -5,73 +5,41 @@ * 2.0. */ -import { isAlertFromEndpointEvent } from '../../utils/endpoint_alert_check'; -import { - isAlertFromSentinelOneEvent, - SENTINEL_ONE_AGENT_ID_FIELD, -} from '../../utils/sentinelone_alert_check'; -import { - CROWDSTRIKE_AGENT_ID_FIELD, - isAlertFromCrowdstrikeEvent, -} from '../../utils/crowdstrike_alert_check'; -import { renderHook } from '@testing-library/react-hooks'; +import type { UseSummaryRowsProps } from './get_alert_summary_rows'; import { useSummaryRows } from './get_alert_summary_rows'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; - -jest.mock('../../utils/endpoint_alert_check'); -jest.mock('../../utils/sentinelone_alert_check'); -jest.mock('../../utils/crowdstrike_alert_check'); -jest.mock('../../hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); +import { createAppRootMockRenderer, endpointAlertDataMock } from '../../mock/endpoint'; +import type { RenderHookResult } from '@testing-library/react-hooks/src/types'; +import type { AlertSummaryRow } from './helpers'; describe('useSummaryRows', () => { - const mockData: TimelineEventsDetailsItem[] = [ - { - category: 'event', - field: 'event.category', - originalValue: ['process'], - values: ['process'], - isObjectArray: false, - }, - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - originalValue: 'rule-uuid', - values: ['rule-uuid'], - isObjectArray: false, - }, - { - category: 'host', - field: 'host.name', - originalValue: 'test-host', - values: ['text-host'], - isObjectArray: false, - }, - ]; - - const mockBrowserFields = {}; - const mockScopeId = 'scope-id'; - const mockEventId = 'event-id'; - const mockInvestigationFields: string[] = []; + let hookProps: UseSummaryRowsProps; + let renderHook: () => RenderHookResult; beforeEach(() => { - jest.clearAllMocks(); - (isAlertFromEndpointEvent as jest.Mock).mockReturnValue(true); - (isAlertFromCrowdstrikeEvent as jest.Mock).mockReturnValue(false); + const appContextMock = createAppRootMockRenderer(); + + appContextMock.setExperimentalFlag({ + responseActionsSentinelOneV1Enabled: true, + responseActionsCrowdstrikeManualHostIsolationEnabled: true, + }); + + hookProps = { + data: endpointAlertDataMock.generateEndpointAlertDetailsItemData(), + browserFields: {}, + scopeId: 'scope-id', + eventId: 'event-id', + investigationFields: [], + }; + + renderHook = () => { + return appContextMock.renderHook(() => + useSummaryRows(hookProps) + ); + }; }); it('returns summary rows for default event categories', () => { - const { result } = renderHook(() => - useSummaryRows({ - data: mockData, - browserFields: mockBrowserFields, - scopeId: mockScopeId, - eventId: mockEventId, - investigationFields: mockInvestigationFields, - }) - ); + const { result } = renderHook(); expect(result.current).toEqual( expect.arrayContaining([ @@ -81,17 +49,7 @@ describe('useSummaryRows', () => { }); it('excludes fields not related to the event source', () => { - (isAlertFromEndpointEvent as jest.Mock).mockReturnValue(false); - - const { result } = renderHook(() => - useSummaryRows({ - data: mockData, - browserFields: mockBrowserFields, - scopeId: mockScopeId, - eventId: mockEventId, - investigationFields: mockInvestigationFields, - }) - ); + const { result } = renderHook(); expect(result.current).not.toEqual( expect.arrayContaining([ @@ -104,70 +62,32 @@ describe('useSummaryRows', () => { }); it('includes sentinel_one agent status field', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - (isAlertFromSentinelOneEvent as jest.Mock).mockReturnValue(true); - - const sentinelOneData: TimelineEventsDetailsItem[] = [ - ...mockData, - { - category: 'host', - field: SENTINEL_ONE_AGENT_ID_FIELD, - originalValue: 'sentinelone-agent-id', - values: ['sentinelone-agent-id'], - isObjectArray: false, - }, - ]; - - const { result } = renderHook(() => - useSummaryRows({ - data: sentinelOneData, - browserFields: mockBrowserFields, - scopeId: mockScopeId, - eventId: mockEventId, - investigationFields: mockInvestigationFields, - }) - ); + hookProps.data = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); + const { result } = renderHook(); expect(result.current).toEqual( expect.arrayContaining([ expect.objectContaining({ title: 'Agent status', - description: expect.objectContaining({ values: ['sentinelone-agent-id'] }), + description: expect.objectContaining({ + values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + }), }), ]) ); }); it('includes crowdstrike agent status field', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - (isAlertFromCrowdstrikeEvent as jest.Mock).mockReturnValue(true); - - const crowdstrikeData: TimelineEventsDetailsItem[] = [ - ...mockData, - { - category: 'host', - field: CROWDSTRIKE_AGENT_ID_FIELD, - originalValue: 'crowdstrike-agent-id', - values: ['crowdstrike-agent-id'], - isObjectArray: false, - }, - ]; - - const { result } = renderHook(() => - useSummaryRows({ - data: crowdstrikeData, - browserFields: mockBrowserFields, - scopeId: mockScopeId, - eventId: mockEventId, - investigationFields: mockInvestigationFields, - }) - ); + hookProps.data = endpointAlertDataMock.generateCrowdStrikeAlertDetailsItemData(); + const { result } = renderHook(); expect(result.current).toEqual( expect.arrayContaining([ expect.objectContaining({ title: 'Agent status', - description: expect.objectContaining({ values: ['crowdstrike-agent-id'] }), + description: expect.objectContaining({ + values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + }), }), ]) ); diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx index b079d3575f7c7..f632e48301b67 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx @@ -9,6 +9,9 @@ import { find, isEmpty, uniqBy } from 'lodash/fp'; import { ALERT_RULE_PARAMETERS, ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { EventCode, EventCategory } from '@kbn/securitysolution-ecs'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../common/endpoint/service/response_actions/constants'; +import { isResponseActionsAlertAgentIdField } from '../../lib/endpoint'; +import { useAlertResponseActionsSupport } from '../../hooks/endpoint/use_alert_response_actions_support'; import * as i18n from './translations'; import type { BrowserFields } from '../../../../common/search_strategy/index_fields'; import { @@ -33,17 +36,6 @@ import { getEnrichedFieldInfo } from './helpers'; import type { EventSummaryField, EnrichedFieldInfo } from './types'; import type { TimelineEventsDetailsItem } from '../../../../common/search_strategy/timeline'; -import { isAlertFromEndpointEvent } from '../../utils/endpoint_alert_check'; -import { - SENTINEL_ONE_AGENT_ID_FIELD, - isAlertFromSentinelOneEvent, -} from '../../utils/sentinelone_alert_check'; -import { - CROWDSTRIKE_AGENT_ID_FIELD, - isAlertFromCrowdstrikeEvent, -} from '../../utils/crowdstrike_alert_check'; -import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; - const THRESHOLD_TERMS_FIELD = `${ALERT_THRESHOLD_RESULT}.terms.field`; const THRESHOLD_TERMS_VALUE = `${ALERT_THRESHOLD_RESULT}.terms.value`; const THRESHOLD_CARDINALITY_FIELD = `${ALERT_THRESHOLD_RESULT}.cardinality.field`; @@ -56,12 +48,12 @@ const alwaysDisplayedFields: EventSummaryField[] = [ // ENDPOINT-related field // { id: 'agent.id', overrideField: AGENT_STATUS_FIELD_NAME, label: i18n.AGENT_STATUS }, { - id: SENTINEL_ONE_AGENT_ID_FIELD, + id: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one, overrideField: AGENT_STATUS_FIELD_NAME, label: i18n.AGENT_STATUS, }, { - id: CROWDSTRIKE_AGENT_ID_FIELD, + id: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.crowdstrike, overrideField: AGENT_STATUS_FIELD_NAME, label: i18n.AGENT_STATUS, }, @@ -307,6 +299,16 @@ export function getEventCategoriesFromData(data: TimelineEventsDetailsItem[]): E return { primaryEventCategory, allEventCategories }; } +export interface UseSummaryRowsProps { + data: TimelineEventsDetailsItem[]; + browserFields: BrowserFields; + scopeId: string; + eventId: string; + investigationFields?: string[]; + isDraggable?: boolean; + isReadOnly?: boolean; +} + export const useSummaryRows = ({ data, browserFields, @@ -315,21 +317,9 @@ export const useSummaryRows = ({ isDraggable = false, isReadOnly = false, investigationFields, -}: { - data: TimelineEventsDetailsItem[]; - browserFields: BrowserFields; - scopeId: string; - eventId: string; - investigationFields?: string[]; - isDraggable?: boolean; - isReadOnly?: boolean; -}) => { - const sentinelOneManualHostActionsEnabled = useIsExperimentalFeatureEnabled( - 'sentinelOneManualHostActionsEnabled' - ); - const crowdstrikeManualHostActionsEnabled = useIsExperimentalFeatureEnabled( - 'responseActionsCrowdstrikeManualHostIsolationEnabled' - ); +}: UseSummaryRowsProps): AlertSummaryRow[] => { + const responseActionsSupport = useAlertResponseActionsSupport(data); + return useMemo(() => { const eventCategories = getEventCategoriesFromData(data); @@ -381,22 +371,14 @@ export const useSummaryRows = ({ isReadOnly, }; - if (field.id === 'agent.id' && !isAlertFromEndpointEvent({ data })) { - return acc; - } - + // If the field is one used by a supported Response Actions agentType, + // and the alert's host supports response actions + // but the alert field is not the one that the agentType on the alert host uses, + // then exit and return accumulator if ( - field.id === SENTINEL_ONE_AGENT_ID_FIELD && - sentinelOneManualHostActionsEnabled && - !isAlertFromSentinelOneEvent({ data }) - ) { - return acc; - } - - if ( - field.id === CROWDSTRIKE_AGENT_ID_FIELD && - crowdstrikeManualHostActionsEnabled && - !isAlertFromCrowdstrikeEvent({ data }) + isResponseActionsAlertAgentIdField(field.id) && + responseActionsSupport.isSupported && + responseActionsSupport.details.agentIdField !== field.id ) { return acc; } @@ -429,15 +411,15 @@ export const useSummaryRows = ({ }, []) : []; }, [ - browserFields, data, + investigationFields, + scopeId, + browserFields, eventId, isDraggable, - scopeId, isReadOnly, - investigationFields, - sentinelOneManualHostActionsEnabled, - crowdstrikeManualHostActionsEnabled, + responseActionsSupport.details.agentIdField, + responseActionsSupport.isSupported, ]); }; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx index dccea29321671..693df1902873a 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx @@ -23,8 +23,7 @@ import { AGENT_STATUS_FIELD_NAME, QUARANTINED_PATH_FIELD_NAME, } from '../../../timelines/components/timeline/body/renderers/constants'; -import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../utils/sentinelone_alert_check'; -import { CROWDSTRIKE_AGENT_ID_FIELD } from '../../utils/crowdstrike_alert_check'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../common/endpoint/service/response_actions/constants'; /** * Defines the behavior of the search input that appears above the table of data @@ -183,8 +182,8 @@ export function getEnrichedFieldInfo({ export const FIELDS_WITHOUT_ACTIONS: { [field: string]: boolean } = { [AGENT_STATUS_FIELD_NAME]: true, [QUARANTINED_PATH_FIELD_NAME]: true, - [SENTINEL_ONE_AGENT_ID_FIELD]: true, - [CROWDSTRIKE_AGENT_ID_FIELD]: true, + [RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one]: true, + [RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.crowdstrike]: true, }; /** diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/__mocks__/use_alert_response_actions_support.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/__mocks__/use_alert_response_actions_support.ts new file mode 100644 index 0000000000000..dcced934f3bc9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/__mocks__/use_alert_response_actions_support.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AlertResponseActionsSupport } from '../use_alert_response_actions_support'; +import { + RESPONSE_ACTION_API_COMMANDS_NAMES, + RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD, +} from '../../../../../common/endpoint/service/response_actions/constants'; + +const useAlertResponseActionsSupportMock = (): AlertResponseActionsSupport => { + return { + isSupported: true, + unsupportedReason: undefined, + isAlert: true, + details: { + agentId: '123', + agentType: 'endpoint', + agentIdField: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.endpoint, + hostName: 'host-a', + platform: 'linux', + agentSupport: RESPONSE_ACTION_API_COMMANDS_NAMES.reduce< + AlertResponseActionsSupport['details']['agentSupport'] + >((acc, responseActionName) => { + acc[responseActionName] = true; + return acc; + }, {} as AlertResponseActionsSupport['details']['agentSupport']), + }, + }; +}; + +export { useAlertResponseActionsSupportMock as useAlertResponseActionsSupport }; diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.test.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.test.ts new file mode 100644 index 0000000000000..b5a07b34c65bb --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.test.ts @@ -0,0 +1,207 @@ +/* + * Copyright 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 { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import type { AppContextTestRender } from '../../mock/endpoint'; +import { createAppRootMockRenderer, endpointAlertDataMock } from '../../mock/endpoint'; +import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; +import { + RESPONSE_ACTION_AGENT_TYPE, + RESPONSE_ACTION_API_COMMANDS_NAMES, + RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD, +} from '../../../../common/endpoint/service/response_actions/constants'; +import type { AlertResponseActionsSupport } from './use_alert_response_actions_support'; +import { + ALERT_EVENT_DATA_MISSING_AGENT_ID_FIELD, + RESPONSE_ACTIONS_ONLY_SUPPORTED_ON_ALERTS, + useAlertResponseActionsSupport, +} from './use_alert_response_actions_support'; +import { isAgentTypeAndActionSupported } from '../../lib/endpoint'; +import type { DeepPartial } from 'utility-types'; +import { merge } from 'lodash'; + +describe('When using `useAlertResponseActionsSupport()` hook', () => { + let appContextMock: AppContextTestRender; + let alertDetailItemData: TimelineEventsDetailsItem[]; + let renderHook: () => ReturnType; + + const getExpectedResult = ( + overrides: DeepPartial = {}, + options: Partial<{ + /* If true, then all properties in `agentSupport` will be false */ + noAgentSupport: boolean; + }> = {} + ): AlertResponseActionsSupport => { + const agentType = overrides.details?.agentType ?? 'endpoint'; + + return merge( + { + isAlert: true, + isSupported: true, + unsupportedReason: undefined, + details: { + agentId: 'abfe4a35-d5b4-42a0-a539-bd054c791769', + agentIdField: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD[agentType], + agentSupport: RESPONSE_ACTION_API_COMMANDS_NAMES.reduce((acc, commandName) => { + acc[commandName] = options.noAgentSupport + ? false + : isAgentTypeAndActionSupported(agentType, commandName); + return acc; + }, {} as AlertResponseActionsSupport['details']['agentSupport']), + agentType, + hostName: 'elastic-host-win', + platform: 'windows', + }, + }, + overrides + ); + }; + + beforeEach(() => { + appContextMock = createAppRootMockRenderer(); + + // Enable feature flags by default + appContextMock.setExperimentalFlag({ + responseActionsSentinelOneV1Enabled: true, + responseActionsSentinelOneGetFileEnabled: true, + responseActionsCrowdstrikeManualHostIsolationEnabled: true, + }); + + alertDetailItemData = endpointAlertDataMock.generateEndpointAlertDetailsItemData(); + renderHook = () => + appContextMock.renderHook(() => useAlertResponseActionsSupport(alertDetailItemData)); + }); + + it.each(RESPONSE_ACTION_AGENT_TYPE)( + 'should return expected response for agentType: `%s`', + (agentType) => { + alertDetailItemData = + endpointAlertDataMock.generateAlertDetailsItemDataForAgentType(agentType); + const { result } = renderHook(); + + expect(result.current).toEqual(getExpectedResult({ details: { agentType } })); + } + ); + + it('should set `isSupported` to `false` if no alert details item data is provided', () => { + alertDetailItemData = []; + + expect(renderHook().result.current).toEqual( + getExpectedResult( + { + isAlert: false, + isSupported: false, + unsupportedReason: RESPONSE_ACTIONS_ONLY_SUPPORTED_ON_ALERTS, + details: { + agentId: '', + agentIdField: '', + hostName: '', + platform: '', + }, + }, + { noAgentSupport: true } + ) + ); + }); + + it('should set `isSupported` to `false` for if not an Alert', () => { + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType( + 'sentinel_one', + { 'kibana.alert.rule.uuid': undefined } + ); + + expect(renderHook().result.current).toEqual( + getExpectedResult({ + isAlert: false, + isSupported: false, + unsupportedReason: RESPONSE_ACTIONS_ONLY_SUPPORTED_ON_ALERTS, + details: { + agentType: 'sentinel_one', + agentIdField: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one, + }, + }) + ); + }); + + it('should set `isSupported` to `false` if unable to get agent id', () => { + alertDetailItemData = endpointAlertDataMock.generateEndpointAlertDetailsItemData({ + [RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.endpoint]: undefined, + }); + + expect(renderHook().result.current).toEqual( + getExpectedResult({ + isSupported: false, + unsupportedReason: ALERT_EVENT_DATA_MISSING_AGENT_ID_FIELD('Elastic Defend', 'agent.id'), + details: { agentId: '' }, + }) + ); + }); + + it('should set `isSupported` to `false` if unable to determine agent type', () => { + alertDetailItemData = endpointAlertDataMock.generateCrowdStrikeAlertDetailsItemData({ + 'event.module': undefined, + }); + + expect(renderHook().result.current).toEqual( + getExpectedResult( + { + isSupported: false, + details: { + agentId: '', + agentIdField: '', + }, + }, + { noAgentSupport: true } + ) + ); + }); + + it('should default `details.agentType` to `endpoint` for non-supported hosts', () => { + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo'); + + expect(renderHook().result.current).toEqual( + getExpectedResult( + { + isSupported: false, + details: { + agentId: '', + agentIdField: '', + }, + }, + { noAgentSupport: true } + ) + ); + }); + + it.each( + RESPONSE_ACTION_AGENT_TYPE.filter((agentType) => agentType !== 'endpoint') as Array< + Exclude + > + )('should set `isSupported` to `false` for [%s] if feature flag is disabled', (agentType) => { + switch (agentType) { + case 'sentinel_one': + appContextMock.setExperimentalFlag({ responseActionsSentinelOneV1Enabled: false }); + break; + case 'crowdstrike': + appContextMock.setExperimentalFlag({ + responseActionsCrowdstrikeManualHostIsolationEnabled: false, + }); + break; + default: + throw new Error(`Unknown agent type: ${agentType}`); + } + + alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType(agentType); + + expect(renderHook().result.current).toEqual( + getExpectedResult({ + isSupported: false, + details: { agentType }, + }) + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts new file mode 100644 index 0000000000000..7d4698695c3b8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts @@ -0,0 +1,241 @@ +/* + * Copyright 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 { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { useMemo } from 'react'; +import { find, some } from 'lodash/fp'; +import { i18n } from '@kbn/i18n'; +import { getAlertDetailsFieldValue } from '../../lib/endpoint/utils/get_event_details_field_values'; +import { isAgentTypeAndActionSupported } from '../../lib/endpoint'; +import type { + ResponseActionAgentType, + ResponseActionsApiCommandNames, +} from '../../../../common/endpoint/service/response_actions/constants'; +import { + RESPONSE_ACTION_API_COMMANDS_NAMES, + RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD, +} from '../../../../common/endpoint/service/response_actions/constants'; +import { getAgentTypeName } from '../../translations'; + +export const ALERT_EVENT_DATA_MISSING_AGENT_ID_FIELD = ( + agentTypeName: string, + missingField: string +): string => { + return i18n.translate( + 'xpack.securitySolution.useAlertResponseActionsSupport.missingAgentIdField', + { + defaultMessage: + 'Alert event data missing {agentTypeName} agent identifier field ({missingField})', + values: { + missingField, + agentTypeName, + }, + } + ); +}; + +export const RESPONSE_ACTIONS_ONLY_SUPPORTED_ON_ALERTS = i18n.translate( + 'xpack.securitySolution.useAlertResponseActionsSupport.notAnAlert', + { defaultMessage: 'Response actions are only supported for Alerts (not events)' } +); + +export interface AlertResponseActionsSupport { + /** Does the host/agent for the given alert have support for response actions */ + isSupported: boolean; + + /** A i18n'd string value indicating the reason why the host does is unsupported */ + unsupportedReason: string | undefined; + + /** + * If the Event Data provide was for a SIEM alert (generated as a result of a Rule run) or + * just an event. + */ + isAlert: boolean; + + /** + * Full details around support for response actions. + * NOTE That some data may not be blank if `isSupported` is `false` + */ + details: { + /** Defaults to `endpoint` when unable to determine agent type */ + agentType: ResponseActionAgentType; + /** Agent ID could be an empty string if `isSupported` is `false` */ + agentId: string; + /** Host name could be an empty string if `isSupported` is `false` */ + hostName: string; + /** The OS platform - normally the ECS value from `host.os.family. could be an empty string if `isSupported` is `false` */ + platform: string; + /** + * A map with the response actions supported by this alert's agent type. This is only what is + * supported, not what the user has privileges to execute. + */ + agentSupport: AlertAgentActionsSupported; + /** The field that was/is used to store the agent ID in the ES document */ + agentIdField: string; + }; +} + +type AlertAgentActionsSupported = Record; + +/** + * Determines the level of support that an alert's host has for Response Actions. + * This hook already checks feature flags to determine the level of support that we have available + */ +export const useAlertResponseActionsSupport = ( + eventData: TimelineEventsDetailsItem[] | null = [] +): AlertResponseActionsSupport => { + const isAlert = useMemo(() => { + return some({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, eventData); + }, [eventData]); + + const agentType: ResponseActionAgentType | undefined = useMemo(() => { + if ((find({ field: 'agent.type' }, eventData)?.values ?? []).includes('endpoint')) { + return 'endpoint'; + } + + const eventModuleValues = find({ field: 'event.module' }, eventData)?.values ?? []; + + if (eventModuleValues.includes('sentinel_one')) { + return 'sentinel_one'; + } + + if (eventModuleValues.includes('crowdstrike')) { + return 'crowdstrike'; + } + + return undefined; + }, [eventData]); + + const isFeatureEnabled: boolean = useMemo(() => { + return agentType ? isAgentTypeAndActionSupported(agentType) : false; + }, [agentType]); + + const agentId: string = useMemo(() => { + if (!agentType) { + return ''; + } + + if (agentType === 'endpoint') { + return getAlertDetailsFieldValue({ category: 'agent', field: 'agent.id' }, eventData); + } + + if (agentType === 'sentinel_one') { + return getAlertDetailsFieldValue( + { category: 'observer', field: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one }, + eventData + ); + } + + if (agentType === 'crowdstrike') { + return getAlertDetailsFieldValue( + { category: 'crowdstrike', field: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.crowdstrike }, + eventData + ); + } + + return ''; + }, [agentType, eventData]); + + const doesHostSupportResponseActions = useMemo(() => { + return Boolean(isFeatureEnabled && isAlert && agentId && agentType); + }, [agentId, agentType, isAlert, isFeatureEnabled]); + + const agentIdField = useMemo(() => { + if (agentType) { + return RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD[agentType]; + } + + return ''; + }, [agentType]); + + const supportedActions = useMemo(() => { + return RESPONSE_ACTION_API_COMMANDS_NAMES.reduce( + (acc, responseActionName) => { + acc[responseActionName] = false; + + if (agentType && isFeatureEnabled) { + acc[responseActionName] = isAgentTypeAndActionSupported( + agentType, + responseActionName, + 'manual' + ); + } + + return acc; + }, + {} as AlertAgentActionsSupported + ); + }, [agentType, isFeatureEnabled]); + + const hostName = useMemo(() => { + // TODO:PT need to check if crowdstrike event has `host.name` + if (agentType === 'crowdstrike') { + return getAlertDetailsFieldValue( + { category: 'crowdstrike', field: 'crowdstrike.event.HostName' }, + eventData + ); + } + + return getAlertDetailsFieldValue({ category: 'host', field: 'host.name' }, eventData); + }, [agentType, eventData]); + + const platform = useMemo(() => { + // TODO:PT need to check if crowdstrike event has `host.os.family` + if (agentType === 'crowdstrike') { + return getAlertDetailsFieldValue( + { category: 'crowdstrike', field: 'crowdstrike.event.Platform' }, + eventData + ); + } + + return getAlertDetailsFieldValue({ category: 'host', field: 'host.os.family' }, eventData); + }, [agentType, eventData]); + + const unsupportedReason = useMemo(() => { + if (!doesHostSupportResponseActions) { + if (!isAlert) { + return RESPONSE_ACTIONS_ONLY_SUPPORTED_ON_ALERTS; + } + + if (!agentType) { + // No message is provided for this condition because the + // return from this hook will always default to `endpoint` + return; + } + + if (!agentId) { + return ALERT_EVENT_DATA_MISSING_AGENT_ID_FIELD(getAgentTypeName(agentType), agentIdField); + } + } + }, [agentId, agentIdField, agentType, doesHostSupportResponseActions, isAlert]); + + return useMemo(() => { + return { + isSupported: doesHostSupportResponseActions, + unsupportedReason, + isAlert, + details: { + agentType: agentType || 'endpoint', + agentId, + hostName, + platform, + agentIdField, + agentSupport: supportedActions, + }, + }; + }, [ + agentId, + agentIdField, + agentType, + doesHostSupportResponseActions, + hostName, + isAlert, + platform, + supportedActions, + unsupportedReason, + ]); +}; diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.test.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/index.test.ts similarity index 91% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.test.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/index.test.ts index ebfac9c6508b6..13c9af46fbac5 100644 --- a/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/index.test.ts @@ -5,16 +5,16 @@ * 2.0. */ -import { KibanaServices } from '../kibana'; +import { KibanaServices } from '../../kibana'; import { coreMock } from '@kbn/core/public/mocks'; import { isolateHost, unIsolateHost } from '.'; import { hostIsolationRequestBodyMock } from './mocks'; import { ISOLATE_HOST_ROUTE_V2, UNISOLATE_HOST_ROUTE_V2, -} from '../../../../common/endpoint/constants'; +} from '../../../../../common/endpoint/constants'; -jest.mock('../kibana'); +jest.mock('../../kibana'); describe('When using Host Isolation library', () => { const mockKibanaServices = KibanaServices.get as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/index.ts similarity index 84% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/index.ts index 71cde358a17a3..dc119de848dec 100644 --- a/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/index.ts @@ -8,12 +8,14 @@ import type { HostIsolationRequestBody, ResponseActionApiResponse, -} from '../../../../common/endpoint/types'; -import { KibanaServices } from '../kibana'; +} from '../../../../../common/endpoint/types'; +import { KibanaServices } from '../../kibana'; import { ISOLATE_HOST_ROUTE_V2, UNISOLATE_HOST_ROUTE_V2, -} from '../../../../common/endpoint/constants'; +} from '../../../../../common/endpoint/constants'; + +// FIXME:PT refactor usage of these and use common hooks /** Isolates a Host running either elastic endpoint or fleet agent */ export const isolateHost = async ( diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/mocks.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/mocks.ts similarity index 81% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/mocks.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/mocks.ts index 5540f4c966773..4881fc3f1569f 100644 --- a/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/mocks.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_isolation/mocks.ts @@ -8,13 +8,13 @@ import type { HostIsolationRequestBody, HostIsolationResponse, -} from '../../../../common/endpoint/types'; -import type { ResponseProvidersInterface } from '../../mock/endpoint/http_handler_mock_factory'; -import { httpHandlerMockFactory } from '../../mock/endpoint/http_handler_mock_factory'; +} from '../../../../../common/endpoint/types'; +import type { ResponseProvidersInterface } from '../../../mock/endpoint/http_handler_mock_factory'; +import { httpHandlerMockFactory } from '../../../mock/endpoint/http_handler_mock_factory'; import { ISOLATE_HOST_ROUTE_V2, UNISOLATE_HOST_ROUTE_V2, -} from '../../../../common/endpoint/constants'; +} from '../../../../../common/endpoint/constants'; export const hostIsolationRequestBodyMock = (): HostIsolationRequestBody => { return { diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.test.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/endpoint_pending_actions.test.ts similarity index 88% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.test.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/endpoint_pending_actions.test.ts index 4431486885a03..2b3a71104ff29 100644 --- a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.test.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/endpoint_pending_actions.test.ts @@ -5,13 +5,13 @@ * 2.0. */ -import { KibanaServices } from '../kibana'; +import { KibanaServices } from '../../kibana'; import { coreMock } from '@kbn/core/public/mocks'; import { fetchPendingActionsByAgentId } from './endpoint_pending_actions'; import { pendingActionsHttpMock, pendingActionsResponseMock } from './mocks'; -import { ACTION_STATUS_ROUTE } from '../../../../common/endpoint/constants'; +import { ACTION_STATUS_ROUTE } from '../../../../../common/endpoint/constants'; -jest.mock('../kibana'); +jest.mock('../../kibana'); describe('when using endpoint pending actions api service', () => { let coreHttp: ReturnType['http']; diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/endpoint_pending_actions.ts similarity index 77% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/endpoint_pending_actions.ts index 3d2d8cd5a4e96..86e3a88cc0d2b 100644 --- a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/endpoint_pending_actions.ts @@ -8,9 +8,11 @@ import type { PendingActionsRequestQuery, PendingActionsResponse, -} from '../../../../common/endpoint/types'; -import { KibanaServices } from '../kibana'; -import { ACTION_STATUS_ROUTE } from '../../../../common/endpoint/constants'; +} from '../../../../../common/endpoint/types'; +import { KibanaServices } from '../../kibana'; +import { ACTION_STATUS_ROUTE } from '../../../../../common/endpoint/constants'; + +// FIXME:PT refactor these to use common hooks /** * Retrieve a list of pending actions against the given Fleet Agent Ids provided on input diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/index.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/index.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/index.ts diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/mocks.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/mocks.ts similarity index 82% rename from x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/mocks.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/mocks.ts index 1ce00bb86ab85..97d91eecc0b38 100644 --- a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/mocks.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/endpoint_pending_actions/mocks.ts @@ -8,10 +8,10 @@ import type { PendingActionsRequestQuery, PendingActionsResponse, -} from '../../../../common/endpoint/types'; -import type { ResponseProvidersInterface } from '../../mock/endpoint/http_handler_mock_factory'; -import { httpHandlerMockFactory } from '../../mock/endpoint/http_handler_mock_factory'; -import { ACTION_STATUS_ROUTE } from '../../../../common/endpoint/constants'; +} from '../../../../../common/endpoint/types'; +import type { ResponseProvidersInterface } from '../../../mock/endpoint/http_handler_mock_factory'; +import { httpHandlerMockFactory } from '../../../mock/endpoint/http_handler_mock_factory'; +import { ACTION_STATUS_ROUTE } from '../../../../../common/endpoint/constants'; export const pendingActionsResponseMock = (): PendingActionsResponse => ({ data: [ diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/index.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/index.ts new file mode 100644 index 0000000000000..5bea833df9cad --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './utils'; +export * from './endpoint_isolation'; +export * from './endpoint_pending_actions'; diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/helpers.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_event_details_field_values.ts similarity index 64% rename from x-pack/plugins/security_solution/public/detections/components/host_isolation/helpers.ts rename to x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_event_details_field_values.ts index 32fa616831dfb..d07b557a8e681 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_event_details_field_values.ts @@ -4,11 +4,18 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { find } from 'lodash/fp'; -import type { TimelineEventsDetailsItem } from '../../../../common/search_strategy'; +import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { find } from 'lodash/fp'; -export const getFieldValues = ( +/** + * Gets the array of values for a given field in an Alert Details data + * + * @param category + * @param field + * @param data + */ +const getEventDetailsFieldValues = ( { category, field, @@ -17,7 +24,7 @@ export const getFieldValues = ( field: string; }, data: TimelineEventsDetailsItem[] | null -) => { +): string[] => { const categoryCompat = category === 'signal' ? 'kibana' : category === 'kibana' ? 'signal' : category; const fieldCompat = @@ -28,11 +35,20 @@ export const getFieldValues = ( : field; return ( find({ category, field }, data)?.values ?? - find({ category: categoryCompat, field: fieldCompat }, data)?.values + find({ category: categoryCompat, field: fieldCompat }, data)?.values ?? + [] ); }; -export const getFieldValue = ( +/** + * Gets a single value for a given Alert Details data field. If the field has multiple values, + * the first one will be returned. + * + * @param category + * @param field + * @param data + */ +export const getAlertDetailsFieldValue = ( { category, field, @@ -41,7 +57,7 @@ export const getFieldValue = ( field: string; }, data: TimelineEventsDetailsItem[] | null -) => { - const currentField = getFieldValues({ category, field }, data); +): string => { + const currentField = getEventDetailsFieldValues({ category, field }, data); return currentField && currentField.length > 0 ? currentField[0] : ''; }; diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/index.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/index.ts new file mode 100644 index 0000000000000..b5e173e2c360f --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './is_agent_type_and_action_supported'; +export * from './is_response_actions_alert_agent_id_field'; diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.test.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.test.ts new file mode 100644 index 0000000000000..79294c165ab22 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.test.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + ResponseActionAgentType, + ResponseActionsApiCommandNames, + ResponseActionType, +} from '../../../../../common/endpoint/service/response_actions/constants'; +import { isAgentTypeAndActionSupported } from './is_agent_type_and_action_supported'; +import { ExperimentalFeaturesService } from '../../../experimental_features_service'; +import type { ExperimentalFeatures } from '../../../../../common'; +import { allowedExperimentalValues } from '../../../../../common'; + +jest.mock('../../../experimental_features_service'); + +describe('isAgentTypeAndActionSupported() util', () => { + const enableFeatures = (overrides: Partial = {}): void => { + (ExperimentalFeaturesService.get as jest.Mock).mockReturnValue({ + ...allowedExperimentalValues, + responseActionsSentinelOneGetFileEnabled: true, + responseActionsCrowdstrikeManualHostIsolationEnabled: true, + ...overrides, + }); + }; + + const disableS1GetFileFeature = () => { + enableFeatures({ responseActionsSentinelOneGetFileEnabled: false }); + }; + + const resetFeatures = (): void => { + (ExperimentalFeaturesService.get as jest.Mock).mockReturnValue({ + ...allowedExperimentalValues, + }); + }; + + beforeEach(() => { + enableFeatures(); + }); + + afterEach(() => { + resetFeatures(); + }); + + it.each` + agentType | actionName | actionType | expectedValue | runSetup + ${'endpoint'} | ${undefined} | ${undefined} | ${true} | ${undefined} + ${'endpoint'} | ${'isolate'} | ${'manual'} | ${true} | ${undefined} + ${'endpoint'} | ${'isolate'} | ${'automated'} | ${true} | ${undefined} + ${'sentinel_one'} | ${undefined} | ${undefined} | ${true} | ${undefined} + ${'sentinel_one'} | ${'isolate'} | ${'manual'} | ${true} | ${undefined} + ${'sentinel_one'} | ${'get-file'} | ${'manual'} | ${true} | ${undefined} + ${'sentinel_one'} | ${'get-file'} | ${undefined} | ${false} | ${disableS1GetFileFeature} + ${'crowdstrike'} | ${undefined} | ${undefined} | ${true} | ${undefined} + ${'crowdstrike'} | ${'isolate'} | ${'manual'} | ${true} | ${undefined} + ${'crowdstrike'} | ${'isolate'} | ${undefined} | ${false} | ${resetFeatures} + `( + 'should return `$expectedValue` for $agentType $actionName ($actionType)', + ({ + agentType, + actionName, + actionType, + expectedValue, + runSetup, + }: { + agentType: ResponseActionAgentType; + actionName?: ResponseActionsApiCommandNames; + actionType?: ResponseActionType; + runSetup?: () => void; + expectedValue: boolean; + }) => { + if (runSetup) { + runSetup(); + } + + expect(isAgentTypeAndActionSupported(agentType, actionName, actionType)).toBe(expectedValue); + } + ); +}); diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.ts new file mode 100644 index 0000000000000..ba70f96f1cfde --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_agent_type_and_action_supported.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + ResponseActionAgentType, + ResponseActionsApiCommandNames, + ResponseActionType, +} from '../../../../../common/endpoint/service/response_actions/constants'; +import { isActionSupportedByAgentType } from '../../../../../common/endpoint/service/response_actions/is_response_action_supported'; +import { ExperimentalFeaturesService } from '../../../experimental_features_service'; + +/** + * Checks if a given Agent type is supported (aka: is feature flag enabled) and optionally + * also checks if a given response action is implemented for that agent type. + */ +export const isAgentTypeAndActionSupported = ( + agentType: ResponseActionAgentType, + actionName?: ResponseActionsApiCommandNames, + actionType: ResponseActionType = 'manual' +): boolean => { + const features = ExperimentalFeaturesService.get(); + const isSentinelOneV1Enabled = features.responseActionsSentinelOneV1Enabled; + const isSentinelOneGetFileEnabled = features.responseActionsSentinelOneGetFileEnabled; + const isCrowdstrikeHostIsolationEnabled = + features.responseActionsCrowdstrikeManualHostIsolationEnabled; + + const isAgentTypeSupported = + agentType === 'endpoint' || + (agentType === 'sentinel_one' && isSentinelOneV1Enabled) || + (agentType === 'crowdstrike' && isCrowdstrikeHostIsolationEnabled); + + let isActionNameSupported: boolean = + !actionName || isActionSupportedByAgentType(agentType, actionName, actionType); + + // if response action is supported, then do specific response action FF checks + if (isAgentTypeSupported && isActionNameSupported && actionName) { + switch (agentType) { + case 'sentinel_one': + switch (actionName) { + case 'get-file': + if (!isSentinelOneGetFileEnabled) { + isActionNameSupported = false; + } + break; + } + + break; + + case 'crowdstrike': + // Placeholder for future individual response actions FF checks + break; + } + } + + return Boolean(isAgentTypeSupported && isActionNameSupported); +}; diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_response_actions_alert_agent_id_field.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_response_actions_alert_agent_id_field.ts new file mode 100644 index 0000000000000..88b940ba3b748 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/is_response_actions_alert_agent_id_field.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../../common/endpoint/service/response_actions/constants'; + +const SUPPORTED_ALERT_FIELDS: Readonly = Object.values( + RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD +); + +/** + * Checks to see if a given alert field (ex. `agent.id`) is used by Agents that have support for response actions. + */ +export const isResponseActionsAlertAgentIdField = (field: string): boolean => { + return SUPPORTED_ALERT_FIELDS.includes(field); +}; diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/endpoint_alert_data_mock.ts b/x-pack/plugins/security_solution/public/common/mock/endpoint/endpoint_alert_data_mock.ts new file mode 100644 index 0000000000000..96003266c1315 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/endpoint_alert_data_mock.ts @@ -0,0 +1,248 @@ +/* + * Copyright 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 { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../common/endpoint/service/response_actions/constants'; + +/** + * Provide overrides for data `fields`. If a field is set to `undefined`, then it will be removed + * from the array. If an override field name is not currently in the array, it will be added. + */ +interface AlertDetailsItemDataOverrides { + [field: string]: Partial | undefined; +} + +/** + * Will update (mutate) the data passed in with the override data defined + * @param data + * @param overrides + */ +const setAlertDetailsItemDataOverrides = ( + data: TimelineEventsDetailsItem[], + overrides: AlertDetailsItemDataOverrides +): TimelineEventsDetailsItem[] => { + if (Object.keys(overrides).length > 0) { + const definedFields: string[] = []; + const deleteIndexes: number[] = []; + + // Override current fields' values + data.forEach((item, index) => { + definedFields.push(item.field); + + if (item.field in overrides) { + // If value is undefined, then mark item for deletion + if (!overrides[item.field]) { + deleteIndexes.unshift(index); + } else { + Object.assign(item, overrides[item.field]); + } + } + }); + + // Delete any items from the array + if (deleteIndexes.length > 0) { + for (const index of deleteIndexes) { + data.splice(index, 1); + } + } + + // Add any new fields to the data + Object.entries(overrides).forEach(([field, fieldData]) => { + if (!definedFields.includes(field)) { + data.push({ + category: 'unknown', + field: 'unknonwn', + values: [], + originalValue: [], + isObjectArray: false, + ...fieldData, + }); + } + }); + } + + return data; +}; + +/** @private */ +const generateEndpointAlertDetailsItemDataMock = ( + overrides: AlertDetailsItemDataOverrides = {} +): TimelineEventsDetailsItem[] => { + const data = [ + { + category: 'kibana', + field: 'kibana.alert.rule.uuid', + values: ['b69d086c-325a-4f46-b17b-fb6d227006ba'], + originalValue: ['b69d086c-325a-4f46-b17b-fb6d227006ba'], + isObjectArray: false, + }, + { + category: 'agent', + field: 'agent.type', + values: ['endpoint'], + originalValue: ['endpoint'], + isObjectArray: false, + }, + { + category: 'agent', + field: 'agent.id', + values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + originalValue: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + isObjectArray: false, + }, + { + category: 'event', + field: 'event.module', + values: ['endpoint'], + originalValue: ['endpoint'], + isObjectArray: false, + }, + { + category: 'event', + field: 'event.category', + originalValue: ['process'], + values: ['process'], + isObjectArray: false, + }, + { + category: 'host', + field: 'host.name', + values: ['elastic-host-win'], + originalValue: ['windows-native'], + isObjectArray: false, + }, + { + category: 'host', + field: 'host.os.family', + values: ['windows'], + originalValue: ['windows'], + isObjectArray: false, + }, + ]; + + setAlertDetailsItemDataOverrides(data, overrides); + + return data; +}; + +/** @private */ +const generateSentinelOneAlertDetailsItemDataMock = ( + overrides: AlertDetailsItemDataOverrides = {} +): TimelineEventsDetailsItem[] => { + const data = generateEndpointAlertDetailsItemDataMock(overrides); + + data.forEach((itemData) => { + switch (itemData.field) { + case 'event.module': + itemData.values = ['sentinel_one']; + itemData.originalValue = ['sentinel_one']; + break; + + case 'agent.type': + itemData.values = ['filebeat']; + itemData.originalValue = ['filebeat']; + break; + } + }); + + data.push({ + category: 'observer', + field: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one, + values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + originalValue: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + isObjectArray: false, + }); + + setAlertDetailsItemDataOverrides(data, overrides); + + return data; +}; + +/** @private */ +const generateCrowdStrikeAlertDetailsItemDataMock = ( + overrides: AlertDetailsItemDataOverrides = {} +): TimelineEventsDetailsItem[] => { + const data = generateEndpointAlertDetailsItemDataMock(); + + data.forEach((itemData) => { + switch (itemData.field) { + case 'event.module': + itemData.values = ['crowdstrike']; + itemData.originalValue = ['crowdstrike']; + break; + + case 'agent.type': + itemData.values = ['filebeat']; + itemData.originalValue = ['filebeat']; + break; + } + }); + + data.push( + { + category: 'crowdstrike', + field: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.crowdstrike, + values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + originalValue: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], + isObjectArray: false, + }, + { + category: 'crowdstrike', + field: 'crowdstrike.event.HostName', + values: ['elastic-host-win'], + originalValue: ['windows-native'], + isObjectArray: false, + }, + { + category: 'crowdstrike', + field: 'crowdstrike.event.Platform', + values: ['windows'], + originalValue: ['windows'], + isObjectArray: false, + } + ); + + setAlertDetailsItemDataOverrides(data, overrides); + + return data; +}; + +/** + * Will return alert details item data for a known agent type or if unknown agent type is + * pass, then data will be for `filebeat` + * @param agentType + * @param overrides + */ +const generateAlertDetailsItemDataForAgentTypeMock = ( + agentType?: ResponseActionAgentType | string, + overrides: AlertDetailsItemDataOverrides = {} +): TimelineEventsDetailsItem[] => { + const unSupportedAgentType = agentType ?? 'filebeat'; + + switch (agentType) { + case 'endpoint': + return generateEndpointAlertDetailsItemDataMock(overrides); + case 'sentinel_one': + return generateSentinelOneAlertDetailsItemDataMock(overrides); + case 'crowdstrike': + return generateCrowdStrikeAlertDetailsItemDataMock(overrides); + default: + return generateEndpointAlertDetailsItemDataMock({ + 'agent.type': { values: [unSupportedAgentType], originalValue: [unSupportedAgentType] }, + 'event.module': { values: [unSupportedAgentType], originalValue: [unSupportedAgentType] }, + ...overrides, + }); + } +}; + +export const endpointAlertDataMock = Object.freeze({ + generateEndpointAlertDetailsItemData: generateEndpointAlertDetailsItemDataMock, + generateSentinelOneAlertDetailsItemData: generateSentinelOneAlertDetailsItemDataMock, + generateCrowdStrikeAlertDetailsItemData: generateCrowdStrikeAlertDetailsItemDataMock, + generateAlertDetailsItemDataForAgentType: generateAlertDetailsItemDataForAgentTypeMock, +}); diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/index.ts b/x-pack/plugins/security_solution/public/common/mock/endpoint/index.ts index 041a8b319ec46..a7d3f604af562 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/index.ts +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/index.ts @@ -7,3 +7,5 @@ export * from './dependencies_start_mock'; export * from './app_context_render'; +export * from './endpoint_alert_data_mock'; +export * from './http_handler_mock_factory'; diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 9720baa0d5aa0..dfb4d29f59371 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -101,7 +101,7 @@ export const UNSAVED_TIMELINE_SAVE_PROMPT_TITLE = i18n.translate( } ); -export const getAgentTypeName = (agentType: ResponseActionAgentType) => { +export const getAgentTypeName = (agentType: ResponseActionAgentType): string => { switch (agentType) { case 'endpoint': return 'Elastic Defend'; diff --git a/x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.test.ts b/x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.test.ts deleted file mode 100644 index 3d585808b8885..0000000000000 --- a/x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; - -import { - isAlertFromCrowdstrikeAlert, - isAlertFromCrowdstrikeEvent, -} from './crowdstrike_alert_check'; - -describe('crowdstrike_alert_check', () => { - describe('isAlertFromCrowdstrikeEvent', () => { - it('returns false if data is not a timeline event alert', () => { - const data: TimelineEventsDetailsItem[] = []; - expect(isAlertFromCrowdstrikeEvent({ data })).toBe(false); - }); - - it('returns false if data is a timeline event alert but not from Crowdstrike', () => { - const data = [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - }, - ] as unknown as TimelineEventsDetailsItem[]; - expect(isAlertFromCrowdstrikeEvent({ data })).toBe(false); - }); - - it('returns true if data is a Crowdstrike timeline event alert', () => { - const data = [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - }, - { - field: 'event.module', - values: ['crowdstrike'], - }, - ] as unknown as TimelineEventsDetailsItem[]; - expect(isAlertFromCrowdstrikeEvent({ data })).toBe(true); - }); - }); - - describe('isAlertFromCrowdstrikeAlert', () => { - it('returns false if ecsData is null', () => { - expect(isAlertFromCrowdstrikeAlert({ ecsData: null })).toBe(false); - }); - - it('returns false if ecsData is not a Crowdstrike alert', () => { - const ecsData = { - 'kibana.alert.original_event.module': ['other'], - 'kibana.alert.original_event.dataset': ['other'], - } as unknown as Ecs; - expect(isAlertFromCrowdstrikeAlert({ ecsData })).toBe(false); - }); - - it('returns true if ecsData is a Crowdstrike alert', () => { - const ecsData = { - 'kibana.alert.original_event.module': ['crowdstrike'], - 'kibana.alert.original_event.dataset': ['alert'], - } as unknown as Ecs; - expect(isAlertFromCrowdstrikeAlert({ ecsData })).toBe(true); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.ts b/x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.ts deleted file mode 100644 index 5bb1befbadd51..0000000000000 --- a/x-pack/plugins/security_solution/public/common/utils/crowdstrike_alert_check.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { find, getOr, some } from 'lodash/fp'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -import { getFieldValue } from '../../detections/components/host_isolation/helpers'; - -/** - * Check to see if a timeline event item is an Alert (vs an event) - * @param timelineEventItem - */ -export const isTimelineEventItemAnAlert = ( - timelineEventItem: TimelineEventsDetailsItem[] -): boolean => { - return some({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, timelineEventItem); -}; - -export const CROWDSTRIKE_AGENT_ID_FIELD = 'crowdstrike.event.DeviceId'; - -export const getCrowdstrikeAgentId = ( - data: TimelineEventsDetailsItem[] | null -): string | undefined => { - return ( - getFieldValue({ category: 'crowdstrike', field: CROWDSTRIKE_AGENT_ID_FIELD }, data) || undefined - ); -}; - -/** - * Checks to see if the given set of Timeline event detail items includes data that indicates its - * an endpoint Alert. Note that it will NOT match on Events - only alerts - * @param data - */ -export const isAlertFromCrowdstrikeEvent = ({ - data, -}: { - data: TimelineEventsDetailsItem[]; -}): boolean => { - if (!isTimelineEventItemAnAlert(data)) { - return false; - } - - const findEndpointAlert = find({ field: 'event.module' }, data)?.values; - return findEndpointAlert ? findEndpointAlert[0] === 'crowdstrike' : false; -}; - -/** - * Checks to see if the given alert was generated out of the Crowdstrike Alerts dataset, coming from - * crowdstrike Fleet integration - * @param ecsData - */ -export const isAlertFromCrowdstrikeAlert = ({ - ecsData, -}: { - ecsData: Ecs | null | undefined; -}): boolean => { - if (ecsData == null) { - return false; - } - - const eventModules = getOr([], 'kibana.alert.original_event.module', ecsData); - const kinds = getOr([], 'kibana.alert.original_event.dataset', ecsData); - - return eventModules.includes('crowdstrike') && kinds.includes('alert'); -}; diff --git a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts deleted file mode 100644 index d62347f6790b3..0000000000000 --- a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import _ from 'lodash'; -import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -import { generateMockDetailItemData } from '../mock'; -import { isAlertFromEndpointAlert, isAlertFromEndpointEvent } from './endpoint_alert_check'; - -describe('isAlertFromEndpointEvent', () => { - let mockDetailItemData: ReturnType; - - beforeEach(() => { - mockDetailItemData = generateMockDetailItemData(); - - // Remove the filebeat agent type from the mock - _.remove(mockDetailItemData, { field: 'agent.type' }); - - mockDetailItemData.push( - // Must be an Alert - { - field: 'kibana.alert.rule.uuid', - category: 'kibana', - originalValue: 'endpoint', - values: ['endpoint'], - isObjectArray: false, - }, - // Must be from an endpoint agent - { - field: 'agent.type', - originalValue: 'endpoint', - values: ['endpoint'], - isObjectArray: false, - } - ); - }); - - it('should return true if detections data comes from an endpoint rule', () => { - expect(isAlertFromEndpointEvent({ data: mockDetailItemData })).toBe(true); - }); - - it('should return false if it is not an Alert (ex. maybe an event)', () => { - _.remove(mockDetailItemData, { field: 'kibana.alert.rule.uuid' }); - expect(isAlertFromEndpointEvent({ data: mockDetailItemData })).toBeFalsy(); - }); - - it('should return false if it is not an endpoint agent', () => { - _.remove(mockDetailItemData, { field: 'agent.type' }); - expect(isAlertFromEndpointEvent({ data: mockDetailItemData })).toBeFalsy(); - }); -}); - -describe('isAlertFromEndpointAlert', () => { - it('should return true if detections data comes from an endpoint rule', () => { - const mockEcsData = { - _id: 'mockId', - 'kibana.alert.original_event.module': ['endpoint'], - 'kibana.alert.original_event.kind': ['alert'], - } as Ecs; - expect(isAlertFromEndpointAlert({ ecsData: mockEcsData })).toBe(true); - }); - - it('should return false if ecsData is undefined', () => { - expect(isAlertFromEndpointAlert({ ecsData: undefined })).toBeFalsy(); - }); - - it('should return false if it is not an Alert', () => { - const mockEcsData = { - _id: 'mockId', - 'kibana.alert.original_event.module': ['endpoint'], - } as Ecs; - expect(isAlertFromEndpointAlert({ ecsData: mockEcsData })).toBeFalsy(); - }); - - it('should return false if it is not an endpoint module', () => { - const mockEcsData = { - _id: 'mockId', - 'kibana.alert.original_event.kind': ['alert'], - } as Ecs; - expect(isAlertFromEndpointAlert({ ecsData: mockEcsData })).toBeFalsy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts deleted file mode 100644 index b755094b679d3..0000000000000 --- a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { find, getOr, some } from 'lodash/fp'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; - -/** - * Check to see if a timeline event item is an Alert (vs an event) - * @param timelineEventItem - */ -export const isTimelineEventItemAnAlert = ( - timelineEventItem: TimelineEventsDetailsItem[] -): boolean => { - return some({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, timelineEventItem); -}; - -/** - * Checks to see if the given set of Timeline event detail items includes data that indicates its - * an endpoint Alert. Note that it will NOT match on Events - only alerts - * @param data - */ -export const isAlertFromEndpointEvent = ({ - data, -}: { - data: TimelineEventsDetailsItem[]; -}): boolean => { - if (!isTimelineEventItemAnAlert(data)) { - return false; - } - - const findEndpointAlert = find({ field: 'agent.type' }, data)?.values; - return findEndpointAlert ? findEndpointAlert[0] === 'endpoint' : false; -}; - -export const isAlertFromEndpointAlert = ({ - ecsData, -}: { - ecsData: Ecs | null | undefined; -}): boolean => { - if (ecsData == null) { - return false; - } - - const eventModules = getOr([], 'kibana.alert.original_event.module', ecsData); - const kinds = getOr([], 'kibana.alert.original_event.kind', ecsData); - - return eventModules.includes('endpoint') && kinds.includes('alert'); -}; diff --git a/x-pack/plugins/security_solution/public/common/utils/sentinelone_alert_check.ts b/x-pack/plugins/security_solution/public/common/utils/sentinelone_alert_check.ts deleted file mode 100644 index b588ba7320144..0000000000000 --- a/x-pack/plugins/security_solution/public/common/utils/sentinelone_alert_check.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { find, getOr, some } from 'lodash/fp'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -import { getFieldValue } from '../../detections/components/host_isolation/helpers'; - -/** - * Check to see if a timeline event item is an Alert (vs an event) - * @param timelineEventItem - */ -export const isTimelineEventItemAnAlert = ( - timelineEventItem: TimelineEventsDetailsItem[] -): boolean => { - return some({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, timelineEventItem); -}; - -export const SENTINEL_ONE_AGENT_ID_FIELD = 'observer.serial_number'; - -export const getSentinelOneAgentId = (data: TimelineEventsDetailsItem[] | null) => - getFieldValue({ category: 'observer', field: SENTINEL_ONE_AGENT_ID_FIELD }, data) || undefined; - -/** - * Checks to see if the given set of Timeline event detail items includes data that indicates its - * an endpoint Alert. Note that it will NOT match on Events - only alerts - * @param data - */ -export const isAlertFromSentinelOneEvent = ({ - data, -}: { - data: TimelineEventsDetailsItem[]; -}): boolean => { - if (!isTimelineEventItemAnAlert(data)) { - return false; - } - - const findEndpointAlert = find({ field: 'event.module' }, data)?.values; - return findEndpointAlert ? findEndpointAlert[0] === 'sentinel_one' : false; -}; - -/** - * Checks to see if the given alert was generated out of the SentinelOne Alerts dataset, coming from - * sentinel_one Fleet integration - * @param ecsData - */ -export const isAlertFromSentinelOneAlert = ({ - ecsData, -}: { - ecsData: Ecs | null | undefined; -}): boolean => { - if (ecsData == null) { - return false; - } - - const eventModules = getOr([], 'kibana.alert.original_event.module', ecsData); - const kinds = getOr([], 'kibana.alert.original_event.dataset', ecsData); - - return eventModules.includes('sentinel_one') && kinds.includes('alert'); -}; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index d18a4c5bf658c..c4afc5ceb5f6a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -11,7 +11,7 @@ import { EuiButtonIcon, EuiContextMenu, EuiPopover, EuiToolTip } from '@elastic/ import { indexOf } from 'lodash'; import { useSelector } from 'react-redux'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { get } from 'lodash/fp'; +import { get, getOr } from 'lodash/fp'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { TableId } from '@kbn/securitysolution-data-table'; import { useRuleWithFallback } from '../../../../detection_engine/rule_management/logic/use_rule_with_fallback'; @@ -46,7 +46,6 @@ import type { import { ATTACH_ALERT_TO_CASE_FOR_ROW } from '../../../../timelines/components/timeline/body/translations'; import { useEventFilterAction } from './use_event_filter_action'; import { useAddToCaseActions } from './use_add_to_case_actions'; -import { isAlertFromEndpointAlert } from '../../../../common/utils/endpoint_alert_check'; import type { Rule } from '../../../../detection_engine/rule_management/logic/types'; import type { AlertTableContextMenuItem } from '../types'; import { useAlertTagsActions } from './use_alert_tags_actions'; @@ -115,6 +114,13 @@ const AlertContextMenuComponent: React.FC = ({ const isEvent = useMemo(() => indexOf(ecsRowData.event?.kind, 'event') !== -1, [ecsRowData]); const isAgentEndpoint = useMemo(() => ecsRowData.agent?.type?.includes('endpoint'), [ecsRowData]); const isEndpointEvent = useMemo(() => isEvent && isAgentEndpoint, [isEvent, isAgentEndpoint]); + const isAlertSourceEndpoint = useMemo(() => { + const eventModules = getOr([], 'kibana.alert.original_event.module', ecsRowData); + const kinds = getOr([], 'kibana.alert.original_event.kind', ecsRowData); + + return eventModules.includes('endpoint') && kinds.includes('alert'); + }, [ecsRowData]); + const scopeIdAllowsAddEndpointEventFilter = useMemo( () => scopeId === TableId.hostsPageEvents || scopeId === TableId.usersPageEvents, [scopeId] @@ -200,7 +206,7 @@ const AlertContextMenuComponent: React.FC = ({ }, [closePopover, onAddEventFilterClick]); const { exceptionActionItems } = useAlertExceptionActions({ - isEndpointAlert: isAlertFromEndpointAlert({ ecsData: ecsRowData }), + isEndpointAlert: isAlertSourceEndpoint, onAddExceptionTypeClick: handleOnAddExceptionTypeClick, }); const { eventFilterActionItems } = useEventFilterAction({ diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.test.ts b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.test.ts deleted file mode 100644 index 9e20b45f55fe6..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getSentinelOneAgentId } from '../../../common/utils/sentinelone_alert_check'; -import { getCrowdstrikeAgentId } from '../../../common/utils/crowdstrike_alert_check'; -import { getExternalEdrAgentInfo } from './get_external_edr_agent_info'; - -jest.mock('../../../common/utils/sentinelone_alert_check'); -jest.mock('../../../common/utils/crowdstrike_alert_check'); - -describe('getExternalEdrAgentInfo', () => { - const mockEventData = [ - { - category: 'event', - field: 'event.module', - values: ['sentinel_one'], - isObjectArray: false, - }, - { - category: 'host', - field: 'host.name', - values: ['test-host'], - isObjectArray: false, - }, - { - category: 'host', - field: 'host.os.name', - values: ['Windows'], - isObjectArray: false, - }, - { - category: 'host', - field: 'host.os.family', - values: ['windows'], - isObjectArray: false, - }, - { - category: 'host', - field: 'host.os.version', - values: ['10'], - isObjectArray: false, - }, - { - category: 'kibana', - field: 'kibana.alert.last_detected', - values: ['2023-05-01T12:34:56Z'], - isObjectArray: false, - }, - { - category: 'crowdstrike', - field: 'crowdstrike.event.HostName', - values: ['test-crowdstrike-host'], - isObjectArray: false, - }, - { - category: 'crowdstrike', - field: 'crowdstrike.event.Platform', - values: ['linux'], - isObjectArray: false, - }, - ]; - - beforeEach(() => { - (getSentinelOneAgentId as jest.Mock).mockReturnValue('sentinel-one-agent-id'); - (getCrowdstrikeAgentId as jest.Mock).mockReturnValue('crowdstrike-agent-id'); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should return correct info for sentinel_one agent type', () => { - const result = getExternalEdrAgentInfo(mockEventData, 'sentinel_one'); - expect(result).toEqual({ - agent: { - id: 'sentinel-one-agent-id', - type: 'sentinel_one', - }, - host: { - name: 'test-host', - os: { - name: 'Windows', - family: 'windows', - version: '10', - }, - }, - lastCheckin: '2023-05-01T12:34:56Z', - }); - }); - - it('should return correct info for crowdstrike agent type', () => { - const result = getExternalEdrAgentInfo(mockEventData, 'crowdstrike'); - expect(result).toEqual({ - agent: { - id: 'crowdstrike-agent-id', - type: 'crowdstrike', - }, - host: { - name: 'test-crowdstrike-host', - os: { - name: '', - family: 'linux', - version: '', - }, - }, - lastCheckin: '2023-05-01T12:34:56Z', - }); - }); - - it('should throw an error for unsupported agent type', () => { - expect(() => { - // @ts-expect-error testing purpose - getExternalEdrAgentInfo(mockEventData, 'unsupported_agent_type'); - }).toThrow('Unsupported agent type: unsupported_agent_type'); - }); -}); diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.ts b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.ts deleted file mode 100644 index 0c9c9ed9f0138..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/get_external_edr_agent_info.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; -import type { ThirdPartyAgentInfo } from '../../../../common/types'; -import { getSentinelOneAgentId } from '../../../common/utils/sentinelone_alert_check'; -import { getFieldValue } from '../host_isolation/helpers'; -import { getCrowdstrikeAgentId } from '../../../common/utils/crowdstrike_alert_check'; - -export const getExternalEdrAgentInfo = ( - eventData: TimelineEventsDetailsItem[], - agentType: ResponseActionAgentType -): ThirdPartyAgentInfo => { - switch (agentType) { - case 'sentinel_one': - return { - agent: { - id: getSentinelOneAgentId(eventData) || '', - type: getFieldValue( - { category: 'event', field: 'event.module' }, - eventData - ) as ResponseActionAgentType, - }, - host: { - name: getFieldValue({ category: 'host', field: 'host.name' }, eventData), - os: { - name: getFieldValue({ category: 'host', field: 'host.os.name' }, eventData), - family: getFieldValue({ category: 'host', field: 'host.os.family' }, eventData), - version: getFieldValue({ category: 'host', field: 'host.os.version' }, eventData), - }, - }, - lastCheckin: getFieldValue( - { category: 'kibana', field: 'kibana.alert.last_detected' }, - eventData - ), - }; - case 'crowdstrike': - return { - agent: { - id: getCrowdstrikeAgentId(eventData) || '', - type: agentType, - }, - host: { - name: getFieldValue( - { category: 'crowdstrike', field: 'crowdstrike.event.HostName' }, - eventData - ), - os: { - name: '', - family: getFieldValue( - { category: 'crowdstrike', field: 'crowdstrike.event.Platform' }, - eventData - ), - version: '', - }, - }, - lastCheckin: getFieldValue( - { category: 'kibana', field: 'kibana.alert.last_detected' }, - eventData - ), - }; - default: - throw new Error(`Unsupported agent type: ${agentType}`); - } -}; diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.test.ts b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.test.ts deleted file mode 100644 index 76be881fa553d..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.test.ts +++ /dev/null @@ -1,233 +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 { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -import { useResponderActionData } from './use_responder_action_data'; -import { renderHook } from '@testing-library/react-hooks'; -import { useGetEndpointDetails } from '../../../management/hooks'; -import { HostStatus } from '../../../../common/endpoint/types'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import { HOST_ENDPOINT_UNENROLLED_TOOLTIP } from './translations'; - -jest.mock('../../../common/hooks/use_experimental_features'); -jest.mock('../../../management/hooks', () => ({ - useGetEndpointDetails: (jest.fn() as jest.Mock).mockImplementation(() => ({ enabled: false })), - useWithShowResponder: jest.fn(), -})); - -const useGetEndpointDetailsMock = useGetEndpointDetails as jest.Mock; -const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; - -describe('#useResponderActionData', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should return `responder` menu item as `disabled` if agentType is not `endpoint` and feature flag is enabled', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(false); - - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'some-agent-type-id', - // @ts-expect-error this is for testing purpose - agentType: 'some_agent_type', - eventData: [], - }) - ); - expect(result.current.isDisabled).toEqual(true); - }); - - describe('when agentType is `endpoint`', () => { - it.each(Object.values(HostStatus).filter((status) => status !== 'unenrolled'))( - 'should return `responder` menu item as `enabled `if agentType is `endpoint` when endpoint is %s', - (hostStatus) => { - useGetEndpointDetailsMock.mockReturnValue({ - data: { - host_status: hostStatus, - }, - isFetching: false, - error: undefined, - }); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'endpoint-id', - agentType: 'endpoint', - }) - ); - expect(result.current.isDisabled).toEqual(false); - } - ); - - it('should return responder menu item `disabled` if agentType is `endpoint` when endpoint is `unenrolled`', () => { - useGetEndpointDetailsMock.mockReturnValue({ - data: { - host_status: 'unenrolled', - }, - isFetching: false, - error: undefined, - }); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'endpoint-id', - agentType: 'endpoint', - }) - ); - expect(result.current.isDisabled).toEqual(true); - }); - - it('should return responder menu item `disabled` if agentType is `endpoint` when endpoint data has error', () => { - useGetEndpointDetailsMock.mockReturnValue({ - data: { - host_status: 'online', - }, - isFetching: false, - error: new Error('uh oh!'), - }); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'endpoint-id', - agentType: 'endpoint', - }) - ); - expect(result.current.isDisabled).toEqual(true); - }); - - it('should return responder menu item `disabled` if agentType is `endpoint` and endpoint data is fetching', () => { - useGetEndpointDetailsMock.mockReturnValue({ - data: undefined, - isFetching: true, - error: undefined, - }); - - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'endpoint-id', - agentType: 'endpoint', - }) - ); - expect(result.current.isDisabled).toEqual(true); - }); - - it('should return responder menu item `disabled` when agentType is `endpoint` but no endpoint id is provided', () => { - const { result } = renderHook(() => - useResponderActionData({ - endpointId: '', - agentType: 'endpoint', - }) - ); - expect(result.current.isDisabled).toEqual(true); - expect(result.current.tooltip).toEqual(HOST_ENDPOINT_UNENROLLED_TOOLTIP); - }); - }); - - describe('when agentType is `sentinel_one`', () => { - const createEventDataMock = (): TimelineEventsDetailsItem[] => { - return [ - { - category: 'observer', - field: 'observer.serial_number', - values: ['c06d63d9-9fa2-046d-e91e-dc94cf6695d8'], - originalValue: ['c06d63d9-9fa2-046d-e91e-dc94cf6695d8'], - isObjectArray: false, - }, - ]; - }; - - it('should return `responder` menu item as `disabled` if agentType is `sentinel_one` and feature flag is disabled', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(false); - - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'sentinel-one-id', - agentType: 'sentinel_one', - eventData: createEventDataMock(), - }) - ); - expect(result.current.isDisabled).toEqual(true); - }); - - it('should return responder menu item as disabled with tooltip if agent id property is missing from event data', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'sentinel-one-id', - agentType: 'sentinel_one', - eventData: [], - }) - ); - expect(result.current.isDisabled).toEqual(true); - expect(result.current.tooltip).toEqual( - 'Event data missing SentinelOne agent identifier (observer.serial_number)' - ); - }); - - it('should return `responder` menu item as `enabled `if agentType is `sentinel_one` and feature flag is enabled', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'sentinel-one-id', - agentType: 'sentinel_one', - eventData: createEventDataMock(), - }) - ); - expect(result.current.isDisabled).toEqual(false); - }); - }); - describe('when agentType is `crowdstrike`', () => { - const createEventDataMock = (): TimelineEventsDetailsItem[] => { - return [ - { - category: 'crowdstrike', - field: 'crowdstrike.event.DeviceId', - values: ['mockedAgentId'], - originalValue: ['mockedAgentId'], - isObjectArray: false, - }, - ]; - }; - - it('should return `responder` menu item as `disabled` if agentType is `crowdstrike` and feature flag is disabled', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(false); - - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'crowdstrike-id', - agentType: 'crowdstrike', - eventData: createEventDataMock(), - }) - ); - expect(result.current.isDisabled).toEqual(true); - }); - - it('should return responder menu item as disabled with tooltip if agent id property is missing from event data', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'crowdstrike-id', - agentType: 'crowdstrike', - eventData: [], - }) - ); - expect(result.current.isDisabled).toEqual(true); - expect(result.current.tooltip).toEqual( - 'Event data missing Crowdstrike agent identifier (crowdstrike.event.DeviceId)' - ); - }); - - it('should return `responder` menu item as `enabled `if agentType is `crowdstrike` and feature flag is enabled', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); - const { result } = renderHook(() => - useResponderActionData({ - endpointId: 'crowdstrike-id', - agentType: 'crowdstrike', - eventData: createEventDataMock(), - }) - ); - expect(result.current.isDisabled).toEqual(false); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts deleted file mode 100644 index b2bf6d22643f4..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts +++ /dev/null @@ -1,175 +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 { ReactNode } from 'react'; -import { useCallback, useMemo } from 'react'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import { getExternalEdrAgentInfo } from './get_external_edr_agent_info'; -import { getCrowdstrikeAgentId } from '../../../common/utils/crowdstrike_alert_check'; -import type { Platform } from '../../../management/components/endpoint_responder/components/header_info/platforms'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -import { getSentinelOneAgentId } from '../../../common/utils/sentinelone_alert_check'; -import type { - ResponseActionAgentType, - EndpointCapabilities, -} from '../../../../common/endpoint/service/response_actions/constants'; -import { useGetEndpointDetails, useWithShowResponder } from '../../../management/hooks'; -import { HostStatus } from '../../../../common/endpoint/types'; -import { - CROWDSTRIKE_AGENT_ID_PROPERTY_MISSING, - HOST_ENDPOINT_UNENROLLED_TOOLTIP, - LOADING_ENDPOINT_DATA_TOOLTIP, - METADATA_API_ERROR_TOOLTIP, - NOT_FROM_ENDPOINT_HOST_TOOLTIP, - SENTINEL_ONE_AGENT_ID_PROPERTY_MISSING, -} from './translations'; - -export interface ResponderContextMenuItemProps { - endpointId: string; - onClick?: () => void; - agentType: ResponseActionAgentType; - eventData?: TimelineEventsDetailsItem[] | null; -} - -/** - * This hook is used to get the data needed to show the context menu items for the responder - * actions. - * @param endpointId the id of the endpoint - * @param onClick the callback to handle the click event - * @param agentType the type of agent, defaults to 'endpoint' - * @param eventData the event data, exists only when agentType !== 'endpoint' - * @returns an object with the data needed to show the context menu item - */ - -export const useResponderActionData = ({ - endpointId, - onClick, - agentType, - eventData, -}: ResponderContextMenuItemProps): { - handleResponseActionsClick: () => void; - isDisabled: boolean; - tooltip: ReactNode; -} => { - const isEndpointHost = agentType === 'endpoint'; - const showResponseActionsConsole = useWithShowResponder(); - - const isSentinelOneV1Enabled = useIsExperimentalFeatureEnabled( - 'responseActionsSentinelOneV1Enabled' - ); - const responseActionsCrowdstrikeManualHostIsolationEnabled = useIsExperimentalFeatureEnabled( - 'responseActionsCrowdstrikeManualHostIsolationEnabled' - ); - const { - data: hostInfo, - isFetching, - error, - } = useGetEndpointDetails(endpointId, { enabled: Boolean(endpointId && isEndpointHost) }); - - const [isDisabled, tooltip]: [disabled: boolean, tooltip: ReactNode] = useMemo(() => { - // v8.13 disabled for third-party agent alerts if the feature flag is not enabled - if (!isEndpointHost) { - switch (agentType) { - case 'sentinel_one': - // Disable it if feature flag is disabled - if (!isSentinelOneV1Enabled) { - return [true, undefined]; - } - // Event must have the property that identifies the agent id - if (!getSentinelOneAgentId(eventData ?? null)) { - return [true, SENTINEL_ONE_AGENT_ID_PROPERTY_MISSING]; - } - - return [false, undefined]; - case 'crowdstrike': - // Disable it if feature flag is disabled - if (!responseActionsCrowdstrikeManualHostIsolationEnabled) { - return [true, undefined]; - } - // Event must have the property that identifies the agent id - if (!getCrowdstrikeAgentId(eventData ?? null)) { - return [true, CROWDSTRIKE_AGENT_ID_PROPERTY_MISSING]; - } - - return [false, undefined]; - - default: - return [true, undefined]; - } - } - - if (!endpointId) { - return [true, HOST_ENDPOINT_UNENROLLED_TOOLTIP]; - } - - // Still loading host info - if (isFetching) { - return [true, LOADING_ENDPOINT_DATA_TOOLTIP]; - } - - // if we got an error, and it's a 404, it means the endpoint is not from the endpoint host - if (error && error.body?.statusCode === 404) { - return [true, NOT_FROM_ENDPOINT_HOST_TOOLTIP]; - } - - // if we got an error and, - // it's a 400 with unenrolled in the error message (alerts can exist for endpoint that are no longer around) - // or, - // the Host status is `unenrolled` - if ( - (error && error.body?.statusCode === 400 && error.body?.message.includes('unenrolled')) || - hostInfo?.host_status === HostStatus.UNENROLLED - ) { - return [true, HOST_ENDPOINT_UNENROLLED_TOOLTIP]; - } - - // return general error tooltip - if (error) { - return [true, METADATA_API_ERROR_TOOLTIP]; - } - - return [false, undefined]; - }, [ - isEndpointHost, - endpointId, - isFetching, - error, - hostInfo?.host_status, - agentType, - isSentinelOneV1Enabled, - eventData, - responseActionsCrowdstrikeManualHostIsolationEnabled, - ]); - - const handleResponseActionsClick = useCallback(() => { - if (!isEndpointHost && eventData != null) { - const agentInfoFromAlert = getExternalEdrAgentInfo(eventData, agentType); - showResponseActionsConsole({ - agentId: agentInfoFromAlert.agent.id, - agentType, - capabilities: ['isolation'], - hostName: agentInfoFromAlert.host.name, - platform: agentInfoFromAlert.host.os.family, - }); - } - if (isEndpointHost && hostInfo) { - showResponseActionsConsole({ - agentId: hostInfo.metadata.agent.id, - agentType, - capabilities: (hostInfo.metadata.Endpoint.capabilities as EndpointCapabilities[]) ?? [], - hostName: hostInfo.metadata.host.name, - platform: hostInfo.metadata.host.os.name.toLowerCase() as Platform, - }); - } - if (onClick) onClick(); - }, [isEndpointHost, hostInfo, onClick, eventData, showResponseActionsConsole, agentType]); - - return { - handleResponseActionsClick, - isDisabled, - tooltip, - }; -}; diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.test.tsx b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.test.tsx deleted file mode 100644 index 750a627985192..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.test.tsx +++ /dev/null @@ -1,144 +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 { renderHook } from '@testing-library/react-hooks'; -import { useResponderActionItem } from './use_responder_action_item'; -import { useUserPrivileges } from '../../../common/components/user_privileges'; -import { isTimelineEventItemAnAlert } from '../../../common/utils/endpoint_alert_check'; -import { getFieldValue } from '../host_isolation/helpers'; -import { isAlertFromCrowdstrikeEvent } from '../../../common/utils/crowdstrike_alert_check'; -import { isAlertFromSentinelOneEvent } from '../../../common/utils/sentinelone_alert_check'; -import { useResponderActionData } from './use_responder_action_data'; - -jest.mock('../../../common/components/user_privileges'); -jest.mock('../../../common/utils/endpoint_alert_check'); -jest.mock('../host_isolation/helpers'); -jest.mock('../../../common/utils/crowdstrike_alert_check'); -jest.mock('../../../common/utils/sentinelone_alert_check'); -jest.mock('./use_responder_action_data'); - -describe('useResponderActionItem', () => { - const mockUseUserPrivileges = useUserPrivileges as jest.Mock; - const mockIsTimelineEventItemAnAlert = isTimelineEventItemAnAlert as jest.Mock; - const mockGetFieldValue = getFieldValue as jest.Mock; - const mockIsAlertFromCrowdstrikeEvent = isAlertFromCrowdstrikeEvent as jest.Mock; - const mockIsAlertFromSentinelOneEvent = isAlertFromSentinelOneEvent as jest.Mock; - const mockUseResponderActionData = useResponderActionData as jest.Mock; - - beforeEach(() => { - jest.clearAllMocks(); - mockUseResponderActionData.mockImplementation(() => ({ - handleResponseActionsClick: jest.fn(), - isDisabled: false, - tooltip: 'Tooltip text', - })); - }); - - it('should return an empty array if user privileges are loading', () => { - mockUseUserPrivileges.mockReturnValue({ - endpointPrivileges: { - loading: true, - canAccessResponseConsole: false, - }, - }); - - const { result } = renderHook(() => useResponderActionItem(null, jest.fn())); - expect(result.current).toEqual([]); - }); - - it('should return an empty array if user cannot access response console', () => { - mockUseUserPrivileges.mockReturnValue({ - endpointPrivileges: { - loading: false, - canAccessResponseConsole: false, - }, - }); - - const { result } = renderHook(() => useResponderActionItem(null, jest.fn())); - expect(result.current).toEqual([]); - }); - - it('should return an empty array if the event is not an alert', () => { - mockUseUserPrivileges.mockReturnValue({ - endpointPrivileges: { - loading: false, - canAccessResponseConsole: true, - }, - }); - mockIsTimelineEventItemAnAlert.mockReturnValue(false); - - const { result } = renderHook(() => useResponderActionItem(null, jest.fn())); - expect(result.current).toEqual([]); - }); - - it('should return the response action item if all conditions are met for a generic endpoint', () => { - mockUseUserPrivileges.mockReturnValue({ - endpointPrivileges: { - loading: false, - canAccessResponseConsole: true, - }, - }); - mockIsTimelineEventItemAnAlert.mockReturnValue(true); - mockGetFieldValue.mockReturnValue('endpoint-id'); - mockIsAlertFromCrowdstrikeEvent.mockReturnValue(false); - mockIsAlertFromSentinelOneEvent.mockReturnValue(false); - - renderHook(() => useResponderActionItem([], jest.fn())); - - expect(mockUseResponderActionData).toHaveBeenCalledWith({ - agentType: 'endpoint', - endpointId: 'endpoint-id', - eventData: null, - onClick: expect.any(Function), - }); - }); - - it('should return the response action item if all conditions are met for a Crowdstrike event', () => { - mockUseUserPrivileges.mockReturnValue({ - endpointPrivileges: { - loading: false, - canAccessResponseConsole: true, - }, - }); - mockIsTimelineEventItemAnAlert.mockReturnValue(true); - mockGetFieldValue.mockReturnValue('crowdstrike-id'); - mockIsAlertFromCrowdstrikeEvent.mockReturnValue(true); - mockIsAlertFromSentinelOneEvent.mockReturnValue(false); - - renderHook(() => useResponderActionItem([], jest.fn())); - - expect(mockUseResponderActionData).toHaveBeenCalledWith({ - agentType: 'crowdstrike', - endpointId: 'crowdstrike-id', - eventData: [], - onClick: expect.any(Function), - }); - }); - - it('should return the response action item if all conditions are met for a SentinelOne event', () => { - mockUseUserPrivileges.mockReturnValue({ - endpointPrivileges: { - loading: false, - canAccessResponseConsole: true, - }, - }); - - mockIsTimelineEventItemAnAlert.mockReturnValue(true); - mockGetFieldValue.mockReturnValue('sentinelone-id'); - mockIsAlertFromCrowdstrikeEvent.mockReturnValue(false); - mockIsAlertFromSentinelOneEvent.mockReturnValue(true); - - renderHook(() => useResponderActionItem([], jest.fn())); - - expect(mockUseResponderActionData).toHaveBeenCalledWith({ - agentType: 'sentinel_one', - endpointId: 'sentinelone-id', - eventData: [], - onClick: expect.any(Function), - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/index.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/index.tsx deleted file mode 100644 index 918de21b704f8..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/index.tsx +++ /dev/null @@ -1,94 +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 React, { useMemo } from 'react'; -import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; -import { getSentinelOneAgentId } from '../../../common/utils/sentinelone_alert_check'; -import { getCrowdstrikeAgentId } from '../../../common/utils/crowdstrike_alert_check'; -import { useCasesFromAlerts } from '../../containers/detection_engine/alerts/use_cases_from_alerts'; -import type { TimelineEventsDetailsItem } from '../../../../common/search_strategy'; -import { getFieldValue } from './helpers'; -import { IsolateHost } from './isolate'; -import { UnisolateHost } from './unisolate'; - -export const HostIsolationPanel = React.memo( - ({ - details, - cancelCallback, - successCallback, - isolateAction, - }: { - details: TimelineEventsDetailsItem[] | null; - cancelCallback: () => void; - successCallback?: () => void; - isolateAction: string; - }) => { - const elasticAgentId = useMemo( - () => getFieldValue({ category: 'agent', field: 'agent.id' }, details), - [details] - ); - - const sentinelOneAgentId = useMemo(() => getSentinelOneAgentId(details), [details]); - const crowdstrikeAgentId = useMemo(() => getCrowdstrikeAgentId(details), [details]); - - const alertId = useMemo( - () => getFieldValue({ category: '_id', field: '_id' }, details), - [details] - ); - - const { casesInfo } = useCasesFromAlerts({ alertId }); - - const agentType: ResponseActionAgentType = useMemo(() => { - if (sentinelOneAgentId) { - return 'sentinel_one'; - } else if (crowdstrikeAgentId) { - return 'crowdstrike'; - } else { - return 'endpoint'; - } - }, [sentinelOneAgentId, crowdstrikeAgentId]); - - const endpointId = useMemo( - () => sentinelOneAgentId ?? crowdstrikeAgentId ?? elasticAgentId, - [elasticAgentId, sentinelOneAgentId, crowdstrikeAgentId] - ); - - const hostName = useMemo(() => { - switch (agentType) { - case 'crowdstrike': - return getFieldValue( - { category: 'crowdstrike', field: 'crowdstrike.event.HostName' }, - details - ); - default: - return getFieldValue({ category: 'host', field: 'host.name' }, details); - } - }, [agentType, details]); - - return isolateAction === 'isolateHost' ? ( - - ) : ( - - ); - } -); - -HostIsolationPanel.displayName = 'HostIsolationContent'; diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.test.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.test.tsx deleted file mode 100644 index 5adbbe58de167..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.test.tsx +++ /dev/null @@ -1,163 +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 { FC, PropsWithChildren } from 'react'; -import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; -import { useHostIsolationAction } from './use_host_isolation_action'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { - useAgentStatusHook, - useGetAgentStatus, - useGetSentinelOneAgentStatus, -} from '../../../management/hooks/agents/use_get_agent_status'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; - -jest.mock('../../../management/hooks/agents/use_get_agent_status'); -jest.mock('../../../common/hooks/use_experimental_features'); - -const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; -const useGetSentinelOneAgentStatusMock = useGetSentinelOneAgentStatus as jest.Mock; -const useGetAgentStatusMock = useGetAgentStatus as jest.Mock; -const useAgentStatusHookMock = useAgentStatusHook as jest.Mock; - -describe('useHostIsolationAction', () => { - describe.each([ - ['useGetSentinelOneAgentStatus', useGetSentinelOneAgentStatusMock], - ['useGetAgentStatus', useGetAgentStatusMock], - ])('works with %s hook', (name, hook) => { - const createReactQueryWrapper = () => { - const queryClient = new QueryClient(); - const wrapper: FC> = ({ children }) => ( - {children} - ); - return wrapper; - }; - - const render = (agentTypeAlert: ResponseActionAgentType) => - renderHook( - () => - useHostIsolationAction({ - closePopover: jest.fn(), - detailsData: - agentTypeAlert === 'sentinel_one' - ? [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - isObjectArray: false, - values: ['ruleId'], - originalValue: ['ruleId'], - }, - { - category: 'event', - field: 'event.module', - values: ['sentinel_one'], - originalValue: ['sentinel_one'], - isObjectArray: false, - }, - { - category: 'observer', - field: 'observer.serial_number', - values: ['some-agent-id'], - originalValue: ['some-agent-id'], - isObjectArray: false, - }, - ] - : agentTypeAlert === 'crowdstrike' - ? [ - { - category: 'kibana', - field: 'kibana.alert.rule.uuid', - isObjectArray: false, - values: ['ruleId'], - originalValue: ['ruleId'], - }, - { - category: 'event', - field: 'event.module', - values: ['crowdstrike'], - originalValue: ['crowdstrike'], - isObjectArray: false, - }, - { - category: 'crowdstrike', - field: 'crowdstrike.event.DeviceId', - values: ['expectedCrowdstrikeAgentId'], - originalValue: ['expectedCrowdstrikeAgentId'], - isObjectArray: false, - }, - ] - : [ - { - category: 'agent', - field: 'agent.id', - values: ['some-agent-id'], - originalValue: ['some-agent-id'], - isObjectArray: false, - }, - ], - isHostIsolationPanelOpen: false, - onAddIsolationStatusClick: jest.fn(), - }), - { - wrapper: createReactQueryWrapper(), - } - ); - - beforeEach(() => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); - useAgentStatusHookMock.mockImplementation(() => hook); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it(`${name} is invoked as 'enabled' when SentinelOne alert and FF enabled`, () => { - render('sentinel_one'); - - expect(hook).toHaveBeenCalledWith(['some-agent-id'], 'sentinel_one', { - enabled: true, - }); - }); - it(`${name} is invoked as 'enabled' when Crowdstrike alert and FF enabled`, () => { - render('crowdstrike'); - - expect(hook).toHaveBeenCalledWith(['expectedCrowdstrikeAgentId'], 'crowdstrike', { - enabled: true, - }); - }); - - it(`${name} is invoked as 'disabled' when SentinelOne alert and FF disabled`, () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(false); - render('sentinel_one'); - - expect(hook).toHaveBeenCalledWith(['some-agent-id'], 'sentinel_one', { - enabled: false, - }); - }); - - it(`${name} is invoked as 'disabled' when Crowdstrike alert and FF disabled`, () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(false); - render('crowdstrike'); - - expect(hook).toHaveBeenCalledWith(['expectedCrowdstrikeAgentId'], 'crowdstrike', { - enabled: false, - }); - }); - - it(`${name} is invoked as 'disabled' when endpoint alert`, () => { - render('endpoint'); - - expect(hook).toHaveBeenCalledWith([''], 'endpoint', { - enabled: false, - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx deleted file mode 100644 index abafc59bef195..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx +++ /dev/null @@ -1,272 +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 { useCallback, useMemo } from 'react'; -import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; -import { useKibana } from '../../../common/lib/kibana/kibana_react'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -import { - getSentinelOneAgentId, - isAlertFromSentinelOneEvent, -} from '../../../common/utils/sentinelone_alert_check'; -import { - getCrowdstrikeAgentId, - isAlertFromCrowdstrikeEvent, -} from '../../../common/utils/crowdstrike_alert_check'; -import { isIsolationSupported } from '../../../../common/endpoint/service/host_isolation/utils'; -import type { AgentStatusInfo } from '../../../../common/endpoint/types'; -import { HostStatus } from '../../../../common/endpoint/types'; -import { isAlertFromEndpointEvent } from '../../../common/utils/endpoint_alert_check'; -import { useEndpointHostIsolationStatus } from '../../containers/detection_engine/alerts/use_host_isolation_status'; -import { ISOLATE_HOST, UNISOLATE_HOST } from './translations'; -import { getFieldValue } from './helpers'; -import { useUserPrivileges } from '../../../common/components/user_privileges'; -import type { AlertTableContextMenuItem } from '../alerts_table/types'; -import { useAgentStatusHook } from '../../../management/hooks/agents/use_get_agent_status'; - -interface UseHostIsolationActionProps { - closePopover: () => void; - detailsData: TimelineEventsDetailsItem[] | null; - isHostIsolationPanelOpen: boolean; - onAddIsolationStatusClick: (action: 'isolateHost' | 'unisolateHost') => void; -} - -export const useHostIsolationAction = ({ - closePopover, - detailsData, - isHostIsolationPanelOpen, - onAddIsolationStatusClick, -}: UseHostIsolationActionProps): AlertTableContextMenuItem[] => { - const useAgentStatus = useAgentStatusHook(); - - const hasActionsAllPrivileges = useKibana().services.application?.capabilities?.actions?.save; - - const agentStatusClientEnabled = useIsExperimentalFeatureEnabled('agentStatusClientEnabled'); - const sentinelOneManualHostActionsEnabled = useIsExperimentalFeatureEnabled( - 'sentinelOneManualHostActionsEnabled' - ); - const crowdstrikeManualHostActionsEnabled = useIsExperimentalFeatureEnabled( - 'responseActionsCrowdstrikeManualHostIsolationEnabled' - ); - - const { canIsolateHost, canUnIsolateHost } = useUserPrivileges().endpointPrivileges; - - const isEndpointAlert = useMemo( - () => isAlertFromEndpointEvent({ data: detailsData || [] }), - [detailsData] - ); - - const isSentinelOneAlert = useMemo( - () => isAlertFromSentinelOneEvent({ data: detailsData || [] }), - [detailsData] - ); - - const isCrowdstrikeAlert = useMemo( - () => isAlertFromCrowdstrikeEvent({ data: detailsData || [] }), - [detailsData] - ); - - const agentId = useMemo( - () => getFieldValue({ category: 'agent', field: 'agent.id' }, detailsData), - [detailsData] - ); - - const sentinelOneAgentId = useMemo(() => getSentinelOneAgentId(detailsData), [detailsData]); - const crowdstrikeAgentId = useMemo(() => getCrowdstrikeAgentId(detailsData), [detailsData]); - - const externalAgentId = sentinelOneAgentId ?? crowdstrikeAgentId ?? ''; - const hostOsFamily = useMemo( - () => getFieldValue({ category: 'host', field: 'host.os.name' }, detailsData), - [detailsData] - ); - - const agentVersion = useMemo( - () => getFieldValue({ category: 'agent', field: 'agent.version' }, detailsData), - [detailsData] - ); - - const agentType = useMemo(() => { - if (isSentinelOneAlert) { - return 'sentinel_one'; - } - if (isCrowdstrikeAlert) { - return 'crowdstrike'; - } - return 'endpoint'; - }, [isCrowdstrikeAlert, isSentinelOneAlert]); - - const { - loading: loadingHostIsolationStatus, - isIsolated, - agentStatus, - capabilities, - } = useEndpointHostIsolationStatus({ - agentId, - agentType, - }); - - const { data: externalAgentData } = useAgentStatus([externalAgentId], agentType, { - enabled: - (!!sentinelOneAgentId && sentinelOneManualHostActionsEnabled) || - (!!crowdstrikeAgentId && crowdstrikeManualHostActionsEnabled), - }); - - const externalAgentStatus = externalAgentData?.[externalAgentId]; - - const isHostIsolated = useMemo(() => { - if ( - (sentinelOneManualHostActionsEnabled && isSentinelOneAlert) || - (crowdstrikeManualHostActionsEnabled && isCrowdstrikeAlert) - ) { - return externalAgentStatus?.isolated; - } - - return isIsolated; - }, [ - isIsolated, - isSentinelOneAlert, - isCrowdstrikeAlert, - externalAgentStatus?.isolated, - sentinelOneManualHostActionsEnabled, - crowdstrikeManualHostActionsEnabled, - ]); - - const doesHostSupportIsolation = useMemo(() => { - if (isEndpointAlert) { - return isIsolationSupported({ - osName: hostOsFamily, - version: agentVersion, - capabilities, - }); - } - - if ( - (externalAgentStatus && sentinelOneManualHostActionsEnabled && isSentinelOneAlert) || - (externalAgentStatus && crowdstrikeManualHostActionsEnabled && isCrowdstrikeAlert) - ) { - return externalAgentStatus.status === 'healthy'; - } - - return false; - }, [ - isEndpointAlert, - sentinelOneManualHostActionsEnabled, - isSentinelOneAlert, - externalAgentStatus, - crowdstrikeManualHostActionsEnabled, - isCrowdstrikeAlert, - hostOsFamily, - agentVersion, - capabilities, - ]); - - const isolateHostHandler = useCallback(() => { - closePopover(); - if (!isHostIsolated) { - onAddIsolationStatusClick('isolateHost'); - } else { - onAddIsolationStatusClick('unisolateHost'); - } - }, [closePopover, isHostIsolated, onAddIsolationStatusClick]); - - const isIsolationActionDisabled = useMemo(() => { - if ( - (sentinelOneManualHostActionsEnabled && isSentinelOneAlert) || - (crowdstrikeManualHostActionsEnabled && isCrowdstrikeAlert) - ) { - // 8.15 use FF for computing if action is enabled - if (agentStatusClientEnabled) { - return externalAgentStatus?.status === HostStatus.UNENROLLED; - } - - // else use the old way - if (!externalAgentStatus) { - return true; - } - - const { isUninstalled, isPendingUninstall } = externalAgentStatus as AgentStatusInfo[string]; - - return isUninstalled || isPendingUninstall; - } - - return agentStatus === HostStatus.UNENROLLED; - }, [ - agentStatus, - agentStatusClientEnabled, - isSentinelOneAlert, - externalAgentStatus, - sentinelOneManualHostActionsEnabled, - crowdstrikeManualHostActionsEnabled, - isCrowdstrikeAlert, - ]); - - const menuItems = useMemo( - () => [ - { - key: 'isolate-host-action-item', - 'data-test-subj': 'isolate-host-action-item', - disabled: isIsolationActionDisabled, - onClick: isolateHostHandler, - name: isHostIsolated ? UNISOLATE_HOST : ISOLATE_HOST, - }, - ], - [isHostIsolated, isolateHostHandler, isIsolationActionDisabled] - ); - - return useMemo(() => { - if (isHostIsolationPanelOpen) { - return []; - } - - if ( - isSentinelOneAlert && - sentinelOneManualHostActionsEnabled && - sentinelOneAgentId && - externalAgentStatus && - hasActionsAllPrivileges - ) { - return menuItems; - } - - if ( - isCrowdstrikeAlert && - crowdstrikeManualHostActionsEnabled && - crowdstrikeAgentId && - externalAgentStatus && - hasActionsAllPrivileges - ) { - return menuItems; - } - - if ( - isEndpointAlert && - doesHostSupportIsolation && - !loadingHostIsolationStatus && - (canIsolateHost || (isHostIsolated && !canUnIsolateHost)) - ) { - return menuItems; - } - - return []; - }, [ - canIsolateHost, - canUnIsolateHost, - doesHostSupportIsolation, - hasActionsAllPrivileges, - isEndpointAlert, - isHostIsolated, - isHostIsolationPanelOpen, - isSentinelOneAlert, - loadingHostIsolationStatus, - menuItems, - externalAgentStatus, - sentinelOneAgentId, - sentinelOneManualHostActionsEnabled, - crowdstrikeAgentId, - isCrowdstrikeAlert, - crowdstrikeManualHostActionsEnabled, - ]); -}; diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx index 442b4b2d4ff62..d8150057dd44b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx @@ -22,26 +22,15 @@ import { useHttp, useKibana } from '../../../common/lib/kibana'; import { mockCasesContract } from '@kbn/cases-plugin/public/mocks'; import { initialUserPrivilegesState as mockInitialUserPrivilegesState } from '../../../common/components/user_privileges/user_privileges_context'; import { useUserPrivileges } from '../../../common/components/user_privileges'; -import { - HOST_ENDPOINT_UNENROLLED_TOOLTIP, - LOADING_ENDPOINT_DATA_TOOLTIP, - NOT_FROM_ENDPOINT_HOST_TOOLTIP, -} from '../endpoint_responder/translations'; -import { endpointMetadataHttpMocks } from '../../../management/pages/endpoint_hosts/mocks'; -import type { HttpSetup } from '@kbn/core/public'; -import { - isAlertFromEndpointAlert, - isAlertFromEndpointEvent, -} from '../../../common/utils/endpoint_alert_check'; import { getUserPrivilegesMockDefaultValue } from '../../../common/components/user_privileges/__mocks__'; import { allCasesPermissions } from '../../../cases_test_utils'; -import { HostStatus } from '../../../../common/endpoint/types'; -import { ENDPOINT_CAPABILITIES } from '../../../../common/endpoint/service/response_actions/constants'; import { ALERT_ASSIGNEES_CONTEXT_MENU_ITEM_TITLE, ALERT_TAGS_CONTEXT_MENU_ITEM_TITLE, } from '../../../common/components/toolbar/bulk_actions/translations'; +jest.mock('../../../common/components/endpoint/host_isolation'); +jest.mock('../../../common/components/endpoint/responder'); jest.mock('../../../common/components/user_privileges'); jest.mock('../user_info', () => ({ @@ -66,34 +55,18 @@ jest.mock('../../../common/hooks/use_license', () => ({ useLicense: jest.fn().mockReturnValue({ isPlatinumPlus: () => true, isEnterprise: () => false }), })); -jest.mock('../../../common/utils/endpoint_alert_check', () => { - const realEndpointAlertCheckUtils = jest.requireActual( - '../../../common/utils/endpoint_alert_check' - ); - return { - isTimelineEventItemAnAlert: realEndpointAlertCheckUtils.isTimelineEventItemAnAlert, - isAlertFromEndpointAlert: jest.fn().mockReturnValue(true), - isAlertFromEndpointEvent: jest.fn().mockReturnValue(true), - }; -}); - -jest.mock('../../../../common/endpoint/service/host_isolation/utils', () => { - return { - isIsolationSupported: jest.fn().mockReturnValue(true), - }; -}); - -jest.mock('../../containers/detection_engine/alerts/use_host_isolation_status', () => { - return { - useEndpointHostIsolationStatus: jest.fn().mockReturnValue({ - loading: false, - isIsolated: false, - agentStatus: 'healthy', - }), - }; -}); - -jest.mock('../../../common/components/user_privileges'); +jest.mock( + '../../../common/components/endpoint/host_isolation/from_alerts/use_host_isolation_status', + () => { + return { + useEndpointHostIsolationStatus: jest.fn().mockReturnValue({ + loading: false, + isIsolated: false, + agentStatus: 'healthy', + }), + }; + } +); describe('take action dropdown', () => { let defaultProps: TakeActionDropdownProps; @@ -292,15 +265,15 @@ describe('take action dropdown', () => { } }; - const setAlertDetailsDataMockToEndpointAgent = () => { + const setAgentTypeOnAlertDetailsDataMock = (agentType: string = 'endpoint') => { if (defaultProps.detailsData) { defaultProps.detailsData = defaultProps.detailsData.map((obj) => { if (obj.field === 'agent.type') { return { category: 'agent', field: 'agent.type', - values: ['endpoint'], - originalValue: ['endpoint'], + values: [agentType], + originalValue: [agentType], }; } if (obj.field === 'agent.id') { @@ -335,9 +308,32 @@ describe('take action dropdown', () => { } }; - describe('should correctly enable/disable the "Add Endpoint event filter" button', () => { - let wrapper: ReactWrapper; + let wrapper: ReactWrapper; + const render = (): ReactWrapper => { + wrapper = mount( + + + + ); + wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); + + return wrapper; + }; + + it('should include the Isolate/Release action', () => { + render(); + + expect(wrapper.exists('[data-test-subj="isolate-host-action-item"]')).toBe(true); + }); + + it('should include the Responder action', () => { + render(); + + expect(wrapper.exists('[data-test-subj="endpointResponseActions-action-item"]')).toBe(true); + }); + + describe('should correctly enable/disable the "Add Endpoint event filter" button', () => { beforeEach(() => { setTypeOnEcsDataWithAgentType(); setAlertDetailsDataMockToEvent(); @@ -348,12 +344,7 @@ describe('take action dropdown', () => { ...mockInitialUserPrivilegesState(), endpointPrivileges: { loading: false, canWriteEventFilters: true }, }); - wrapper = mount( - - - - ); - wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); + render(); await waitFor(() => { expect( wrapper.find('[data-test-subj="add-event-filter-menu-item"]').last().getDOMNode() @@ -366,204 +357,18 @@ describe('take action dropdown', () => { ...mockInitialUserPrivilegesState(), endpointPrivileges: { loading: false, canWriteEventFilters: false }, }); - wrapper = mount( - - - - ); - wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); + render(); await waitFor(() => { expect(wrapper.exists('[data-test-subj="add-event-filter-menu-item"]')).toBeFalsy(); }); }); test('should hide the "Add Endpoint event filter" button if provided no event from endpoint', async () => { + setAgentTypeOnAlertDetailsDataMock('filebeat'); setTypeOnEcsDataWithAgentType('filebeat'); - - wrapper = mount( - - - - ); - wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); - await waitFor(() => { - expect(wrapper.exists('[data-test-subj="add-event-filter-menu-item"]')).toBeFalsy(); - }); - }); - }); - - describe('should correctly enable/disable the "Isolate Host" button', () => { - let wrapper: ReactWrapper; - - const render = (): ReactWrapper => { - wrapper = mount( - - - - ); - wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); - - return wrapper; - }; - - const isolateHostButtonExists = (): ReturnType => { - return wrapper.exists('[data-test-subj="isolate-host-action-item"]'); - }; - - beforeEach(() => { - setTypeOnEcsDataWithAgentType(); - }); - - it('should show Isolate host button if user has "Host isolation" privileges set to all', async () => { - (useUserPrivileges as jest.Mock).mockReturnValue({ - ...mockInitialUserPrivilegesState(), - endpointPrivileges: { loading: false, canIsolateHost: true }, - }); - render(); - - await waitFor(() => { - expect(isolateHostButtonExists()).toBeTruthy(); - }); - }); - it('should hide Isolate host button if user has "Host isolation" privileges set to none', () => { - (useUserPrivileges as jest.Mock).mockReturnValue({ - ...mockInitialUserPrivilegesState(), - endpointPrivileges: { loading: false, canIsolateHost: false }, - }); - render(); - - expect(isolateHostButtonExists()).toBeFalsy(); - }); - }); - - describe('should correctly enable/disable the "Respond" button', () => { - let wrapper: ReactWrapper; - let apiMocks: ReturnType; - - const render = (): ReactWrapper => { - wrapper = mount( - - - - ); - wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); - - return wrapper; - }; - - const findLaunchResponderButton = (): ReturnType => { - return wrapper.find('[data-test-subj="endpointResponseActions-action-item"]'); - }; - - beforeAll(() => { - // Un-Mock endpoint alert check hooks - const actualChecks = jest.requireActual('../../../common/utils/endpoint_alert_check'); - (isAlertFromEndpointEvent as jest.Mock).mockImplementation( - actualChecks.isAlertFromEndpointEvent - ); - (isAlertFromEndpointAlert as jest.Mock).mockImplementation( - actualChecks.isAlertFromEndpointAlert - ); - }); - - afterAll(() => { - // Set the mock modules back to what they were - (isAlertFromEndpointEvent as jest.Mock).mockImplementation(() => true); - (isAlertFromEndpointAlert as jest.Mock).mockImplementation(() => true); - }); - - beforeEach(() => { - setTypeOnEcsDataWithAgentType(); - apiMocks = endpointMetadataHttpMocks(mockStartServicesMock.http as jest.Mocked); - }); - - it('should not display the button if user is not allowed to write event filters', async () => { - (useUserPrivileges as jest.Mock).mockReturnValue({ - ...mockInitialUserPrivilegesState(), - endpointPrivileges: { loading: false, canWriteEventFilters: false }, - }); - render(); - - expect(findLaunchResponderButton()).toHaveLength(0); - }); - - it('should not display the button for Events', async () => { - setAlertDetailsDataMockToEvent(); - render(); - - expect(findLaunchResponderButton()).toHaveLength(0); - }); - - it('should enable button for non endpoint event type when defend integration present', async () => { - setTypeOnEcsDataWithAgentType('filebeat'); - if (defaultProps.detailsData) { - defaultProps.detailsData = generateAlertDetailsDataMock() as TimelineEventsDetailsItem[]; - } - render(); - - expect(findLaunchResponderButton().first().prop('disabled')).toBe(true); - expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual( - LOADING_ENDPOINT_DATA_TOOLTIP - ); - - await waitFor(() => { - expect(apiMocks.responseProvider.metadataDetails).toHaveBeenCalled(); - wrapper.update(); - - expect(findLaunchResponderButton().first().prop('disabled')).toBe(false); - expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual(undefined); - }); - }); - - it('should disable the button for non endpoint event type when defend integration not present', async () => { - setAlertDetailsDataMockToEndpointAgent(); - apiMocks.responseProvider.metadataDetails.mockImplementation(() => { - const error: Error & { body?: { statusCode: number } } = new Error(); - error.body = { statusCode: 404 }; - throw error; - }); render(); - await waitFor(() => { - expect(apiMocks.responseProvider.metadataDetails).toThrow(); - wrapper.update(); - - expect(findLaunchResponderButton().first().prop('disabled')).toBe(true); - expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual( - NOT_FROM_ENDPOINT_HOST_TOOLTIP - ); - }); - }); - - it('should disable the button if host status is unenrolled', async () => { - setAlertDetailsDataMockToEndpointAgent(); - const getApiResponse = apiMocks.responseProvider.metadataDetails.getMockImplementation(); - apiMocks.responseProvider.metadataDetails.mockImplementation(() => { - if (getApiResponse) { - return { - ...getApiResponse(), - metadata: { - ...getApiResponse().metadata, - Endpoint: { - ...getApiResponse().metadata.Endpoint, - capabilities: [...ENDPOINT_CAPABILITIES], - }, - }, - host_status: HostStatus.UNENROLLED, - }; - } - throw new Error('some error'); - }); - render(); - - await waitFor(() => { - expect(apiMocks.responseProvider.metadataDetails).toHaveBeenCalled(); - wrapper.update(); - - expect(findLaunchResponderButton().first().prop('disabled')).toBe(true); - expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual( - HOST_ENDPOINT_UNENROLLED_TOOLTIP - ); + expect(wrapper.exists('[data-test-subj="add-event-filter-menu-item"]')).toBeFalsy(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx index 2c769b81b0481..1f4baaeae8df5 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx @@ -11,23 +11,21 @@ import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-typ import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { TableId } from '@kbn/securitysolution-data-table'; import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { getAlertDetailsFieldValue } from '../../../common/lib/endpoint/utils/get_event_details_field_values'; import { GuidedOnboardingTourStep } from '../../../common/components/guided_onboarding_tour/tour_step'; import { AlertsCasesTourSteps, SecurityStepId, } from '../../../common/components/guided_onboarding_tour/tour_config'; import { isActiveTimeline } from '../../../helpers'; -import { useResponderActionItem } from '../endpoint_responder'; import { TAKE_ACTION } from '../alerts_table/additional_filters_action/translations'; import { useAlertExceptionActions } from '../alerts_table/timeline_actions/use_add_exception_actions'; import { useAlertsActions } from '../alerts_table/timeline_actions/use_alerts_actions'; import { useInvestigateInTimeline } from '../alerts_table/timeline_actions/use_investigate_in_timeline'; - import { useEventFilterAction } from '../alerts_table/timeline_actions/use_event_filter_action'; -import { useHostIsolationAction } from '../host_isolation/use_host_isolation_action'; -import { getFieldValue } from '../host_isolation/helpers'; +import { useResponderActionItem } from '../../../common/components/endpoint/responder'; +import { useHostIsolationAction } from '../../../common/components/endpoint/host_isolation'; import type { Status } from '../../../../common/api/detection_engine'; -import { isAlertFromEndpointAlert } from '../../../common/utils/endpoint_alert_check'; import { useUserPrivileges } from '../../../common/components/user_privileges'; import { useAddToCaseActions } from '../alerts_table/timeline_actions/use_add_to_case_actions'; import { useKibana } from '../../../common/lib/kibana'; @@ -97,7 +95,10 @@ export const TakeActionDropdown = React.memo( ].reduce( (acc, curr) => ({ ...acc, - [curr.name]: getFieldValue({ category: curr.category, field: curr.field }, detailsData), + [curr.name]: getAlertDetailsFieldValue( + { category: curr.category, field: curr.field }, + detailsData + ), }), {} as ActionsData ), @@ -107,11 +108,10 @@ export const TakeActionDropdown = React.memo( const isEvent = actionsData.eventKind === 'event'; const isAgentEndpoint = useMemo(() => ecsData?.agent?.type?.includes('endpoint'), [ecsData]); - const isEndpointEvent = useMemo(() => isEvent && isAgentEndpoint, [isEvent, isAgentEndpoint]); - const agentId = useMemo( - () => getFieldValue({ category: 'agent', field: 'agent.id' }, detailsData), + const osqueryAgentId = useMemo( + () => getAlertDetailsFieldValue({ category: 'agent', field: 'agent.id' }, detailsData), [detailsData] ); @@ -157,7 +157,7 @@ export const TakeActionDropdown = React.memo( ); const { exceptionActionItems } = useAlertExceptionActions({ - isEndpointAlert: isAlertFromEndpointAlert({ ecsData }), + isEndpointAlert: Boolean(isAgentEndpoint), onAddExceptionTypeClick: handleOnAddExceptionTypeClick, }); @@ -208,13 +208,13 @@ export const TakeActionDropdown = React.memo( }); const osqueryAvailable = osquery?.isOsqueryAvailable({ - agentId, + agentId: osqueryAgentId, }); const handleOnOsqueryClick = useCallback(() => { - onOsqueryClick(agentId); + onOsqueryClick(osqueryAgentId); setIsPopoverOpen(false); - }, [onOsqueryClick, setIsPopoverOpen, agentId]); + }, [onOsqueryClick, setIsPopoverOpen, osqueryAgentId]); const osqueryActionItem = useMemo( () => diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts index 815628f8a3d4a..0b198793a31ff 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts @@ -30,7 +30,7 @@ import type { CheckSignalIndex, UpdateAlertStatusByIdsProps, } from './types'; -import { isolateHost, unIsolateHost } from '../../../../common/lib/endpoint_isolation'; +import { isolateHost, unIsolateHost } from '../../../../common/lib/endpoint/endpoint_isolation'; import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables'; /** diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx index 2a6e51d5839a8..f60866be1e3ea 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx @@ -77,7 +77,7 @@ import { useSourcererDataView } from '../../../../sourcerer/containers'; import { EmptyPrompt } from '../../../../common/components/empty_prompt'; import { AlertCountByRuleByStatus } from '../../../../common/components/alert_count_by_status'; import { useLicense } from '../../../../common/hooks/use_license'; -import { ResponderActionButton } from '../../../../detections/components/endpoint_responder/responder_action_button'; +import { ResponderActionButton } from '../../../../common/components/endpoint/responder'; import { useRefetchOverviewPageRiskScore } from '../../../../entity_analytics/api/hooks/use_refetch_overview_page_risk_score'; const ES_HOST_FIELD = 'host.name'; @@ -226,7 +226,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta rightSideItems={[ hostOverview.endpoint?.hostInfo?.metadata.elastic.agent.id && ( ), diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx index ae7707e971131..6c4aafa0f7bd4 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/content.tsx @@ -10,10 +10,12 @@ import React, { useCallback } from 'react'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { DocumentDetailsRightPanelKey } from '../shared/constants/panel_keys'; import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers'; -import { EndpointIsolateSuccess } from '../../../common/components/endpoint/host_isolation'; +import { + EndpointIsolateSuccess, + HostIsolationPanel, +} from '../../../common/components/endpoint/host_isolation'; import { useHostIsolationTools } from '../../../timelines/components/side_panel/event_details/use_host_isolation_tools'; import { useIsolateHostPanelContext } from './context'; -import { HostIsolationPanel } from '../../../detections/components/host_isolation'; import { FlyoutBody } from '../../shared/components/flyout_body'; /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.test.tsx index 5df180ed58075..63fd7651f04aa 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.test.tsx @@ -6,128 +6,95 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; -import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import type { IsolateHostPanelContext } from './context'; import { useIsolateHostPanelContext } from './context'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { PanelHeader } from './header'; -import { FLYOUT_HEADER_TITLE_TEST_ID } from './test_ids'; -import { isAlertFromSentinelOneEvent } from '../../../common/utils/sentinelone_alert_check'; -import { isAlertFromCrowdstrikeEvent } from '../../../common/utils/crowdstrike_alert_check'; +import type { AppContextTestRender } from '../../../common/mock/endpoint'; +import { createAppRootMockRenderer, endpointAlertDataMock } from '../../../common/mock/endpoint'; +import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; +import { RESPONSE_ACTION_AGENT_TYPE } from '../../../../common/endpoint/service/response_actions/constants'; +import { ISOLATE_HOST, UNISOLATE_HOST } from '../../../common/components/endpoint/host_isolation'; import { TECHNICAL_PREVIEW } from '../../../common/translations'; -jest.mock('../../../common/hooks/use_experimental_features'); -jest.mock('../../../common/utils/sentinelone_alert_check'); -jest.mock('../../../common/utils/crowdstrike_alert_check'); jest.mock('./context'); -const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; -const mockIsAlertFromSentinelOneEvent = isAlertFromSentinelOneEvent as jest.Mock; -const mockIsAlertFromCrowdstrike = isAlertFromCrowdstrikeEvent as jest.Mock; +describe('Isolation Flyout PanelHeader', () => { + let render: () => ReturnType; -const renderPanelHeader = () => - render( - - - - ); + const setUseIsolateHostPanelContext = (data: Partial = {}) => { + const panelContextMock: IsolateHostPanelContext = { + eventId: 'some-even-1', + indexName: 'some-index-name', + scopeId: 'some-scope-id', + dataFormattedForFieldBrowser: endpointAlertDataMock.generateEndpointAlertDetailsItemData(), + isolateAction: 'isolateHost', + ...data, + }; + + (useIsolateHostPanelContext as jest.Mock).mockReturnValue(panelContextMock); + }; -describe('', () => { beforeEach(() => { - mockUseIsExperimentalFeatureEnabled.mockReturnValue(false); - mockIsAlertFromSentinelOneEvent.mockReturnValue(false); - mockIsAlertFromCrowdstrike.mockReturnValue(false); - }); + const appContextMock = createAppRootMockRenderer(); - it.each([ - { - isolateAction: 'isolateHost', - title: 'Isolate host', - }, - { - isolateAction: 'unisolateHost', - title: 'Release host', - }, - ])('should display release host message', ({ isolateAction, title }) => { - (useIsolateHostPanelContext as jest.Mock).mockReturnValue({ isolateAction }); + appContextMock.setExperimentalFlag({ + responseActionsSentinelOneV1Enabled: true, + responseActionsCrowdstrikeManualHostIsolationEnabled: true, + }); - const { getByTestId } = renderPanelHeader(); + render = () => appContextMock.render(); - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toBeInTheDocument(); - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toHaveTextContent(title); + setUseIsolateHostPanelContext({ + isolateAction: 'isolateHost', + dataFormattedForFieldBrowser: endpointAlertDataMock.generateEndpointAlertDetailsItemData(), + }); }); - it.each([ - { - action: 'isolateHost', - alertCheck: mockIsAlertFromSentinelOneEvent, - description: 'SentinelOne', - }, - { - action: 'unisolateHost', - alertCheck: mockIsAlertFromSentinelOneEvent, - description: 'SentinelOne', - }, - { - action: 'isolateHost', - alertCheck: mockIsAlertFromCrowdstrike, - description: 'Crowdstrike', - }, - { - action: 'unisolateHost', - alertCheck: mockIsAlertFromCrowdstrike, - description: 'Crowdstrike', - }, - ])( - 'should display beta badge on $description alerts for %s host message', - ({ action, alertCheck }) => { - (useIsolateHostPanelContext as jest.Mock).mockReturnValue({ - isolateAction: action, - }); - mockUseIsExperimentalFeatureEnabled.mockReturnValue(true); - alertCheck.mockReturnValue(true); + afterEach(() => { + jest.clearAllMocks(); + }); - const { getByTestId } = renderPanelHeader(); + const testConditions: Array<{ + action: IsolateHostPanelContext['isolateAction']; + agentType: ResponseActionAgentType; + title: string; + // if `expectedBadgeText` is `undefined`, then it validates that the badge is not displayed + expectedBadgeText: string | undefined; + }> = []; - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toBeInTheDocument(); - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toHaveTextContent(TECHNICAL_PREVIEW); - } - ); + for (const agentType of RESPONSE_ACTION_AGENT_TYPE) { + (['isolateHost', 'unisolateHost'] as Array).forEach( + (action) => { + testConditions.push({ + action, + agentType, + title: action === 'isolateHost' ? ISOLATE_HOST : UNISOLATE_HOST, + expectedBadgeText: + agentType === 'crowdstrike' || agentType === 'sentinel_one' + ? TECHNICAL_PREVIEW + : undefined, + }); + } + ); + } - it.each([ - { - action: 'isolateHost', - alertCheck: mockIsAlertFromSentinelOneEvent, - description: 'SentinelOne', - }, - { - action: 'unisolateHost', - alertCheck: mockIsAlertFromSentinelOneEvent, - description: 'SentinelOne', - }, - { - action: 'isolateHost', - alertCheck: mockIsAlertFromCrowdstrike, - description: 'Crowdstrike', - }, - { - action: 'unisolateHost', - alertCheck: mockIsAlertFromCrowdstrike, - description: 'Crowdstrike', - }, - ])( - 'should not display beta badge on $description alerts for %s host message', - ({ action, alertCheck }) => { - (useIsolateHostPanelContext as jest.Mock).mockReturnValue({ + it.each(testConditions)( + 'should display correct flyout header title for $action on agentType $agentType', + ({ action, agentType, title, expectedBadgeText }) => { + setUseIsolateHostPanelContext({ isolateAction: action, + dataFormattedForFieldBrowser: + endpointAlertDataMock.generateAlertDetailsItemDataForAgentType(agentType), }); - mockUseIsExperimentalFeatureEnabled.mockReturnValue(true); - alertCheck.mockReturnValue(false); + const { getByTestId, queryByTestId } = render(); - const { getByTestId } = renderPanelHeader(); + expect(getByTestId('flyoutHostIsolationHeaderTitle')).toHaveTextContent(title); - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toBeInTheDocument(); - expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).not.toHaveTextContent(TECHNICAL_PREVIEW); + if (expectedBadgeText) { + expect(getByTestId('flyoutHostIsolationHeaderBadge')).toHaveTextContent(expectedBadgeText); + } else { + expect(queryByTestId('flyoutHostIsolationHeaderBadge')).toBeNull(); + } } ); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx index ead599d38e498..635d273b43237 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/isolate_host/header.tsx @@ -7,51 +7,40 @@ import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import type { FC } from 'react'; -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { isAlertFromCrowdstrikeEvent } from '../../../common/utils/crowdstrike_alert_check'; +import React, { useMemo } from 'react'; +import { useAlertResponseActionsSupport } from '../../../common/hooks/endpoint/use_alert_response_actions_support'; import { TECHNICAL_PREVIEW, TECHNICAL_PREVIEW_TOOLTIP } from '../../../common/translations'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -import { isAlertFromSentinelOneEvent } from '../../../common/utils/sentinelone_alert_check'; import { useIsolateHostPanelContext } from './context'; import { FLYOUT_HEADER_TITLE_TEST_ID } from './test_ids'; import { FlyoutHeader } from '../../shared/components/flyout_header'; +import { ISOLATE_HOST, UNISOLATE_HOST } from '../../../common/components/endpoint'; /** * Document details expandable right section header for the isolate host panel */ export const PanelHeader: FC = () => { const { isolateAction, dataFormattedForFieldBrowser: data } = useIsolateHostPanelContext(); - const isSentinelOneAlert = isAlertFromSentinelOneEvent({ data }); - const isSentinelOneV1Enabled = useIsExperimentalFeatureEnabled( - 'responseActionsSentinelOneV1Enabled' - ); + const { + isSupported: supportsResponseActions, + details: { agentType }, + } = useAlertResponseActionsSupport(data); + + const showTechPreviewBadge: boolean = useMemo(() => { + return supportsResponseActions && (agentType === 'sentinel_one' || agentType === 'crowdstrike'); + }, [agentType, supportsResponseActions]); - const isAlertFromCrowdstrikeAlert = isAlertFromCrowdstrikeEvent({ data }); - const responseActionsCrowdstrikeManualHostIsolationEnabled = useIsExperimentalFeatureEnabled( - 'responseActionsCrowdstrikeManualHostIsolationEnabled' - ); - const showAsTechPreview = - (isSentinelOneV1Enabled && isSentinelOneAlert) || - (responseActionsCrowdstrikeManualHostIsolationEnabled && isAlertFromCrowdstrikeAlert); const title = ( - - {isolateAction === 'isolateHost' ? ( - - ) : ( - - )} + + {isolateAction === 'isolateHost' ? <>{ISOLATE_HOST} : <>{UNISOLATE_HOST}} - {showAsTechPreview && ( + {showTechPreviewBadge && ( - + )} diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.tsx index be495a6b16df6..51e60b67ed8b0 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/highlighted_fields_cell.tsx @@ -11,12 +11,10 @@ import { EuiFlexItem, EuiLink } from '@elastic/eui'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import type { ResponseActionAgentType } from '../../../../../common/endpoint/service/response_actions/constants'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; -import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../common/utils/sentinelone_alert_check'; import { AgentStatus, EndpointAgentStatusById, -} from '../../../../common/components/agents/agent_status'; -import { CROWDSTRIKE_AGENT_ID_FIELD } from '../../../../common/utils/crowdstrike_alert_check'; +} from '../../../../common/components/endpoint/agents/agent_status'; import { useRightPanelContext } from '../context'; import { AGENT_STATUS_FIELD_NAME, @@ -32,6 +30,7 @@ import { HIGHLIGHTED_FIELDS_CELL_TEST_ID, HIGHLIGHTED_FIELDS_LINKED_CELL_TEST_ID, } from './test_ids'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../../common/endpoint/service/response_actions/constants'; interface LinkFieldCellProps { /** @@ -117,11 +116,11 @@ export const HighlightedFieldsCell: VFC = ({ originalField, }) => { const isSentinelOneAgentIdField = useMemo( - () => originalField === SENTINEL_ONE_AGENT_ID_FIELD, + () => originalField === RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one, [originalField] ); const isCrowdstrikeAgentIdField = useMemo( - () => originalField === CROWDSTRIKE_AGENT_ID_FIELD, + () => originalField === RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.crowdstrike, [originalField] ); const agentType: ResponseActionAgentType = useMemo(() => { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.test.tsx index 3a18b49a0fc17..c78e7313792c8 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.test.tsx @@ -12,7 +12,9 @@ import { mockDataFormattedForFieldBrowserWithOverridenField, } from '../mocks/mock_data_formatted_for_field_browser'; import { useHighlightedFields } from './use_highlighted_fields'; -import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../common/utils/sentinelone_alert_check'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../../common/endpoint/service/response_actions/constants'; + +jest.mock('../../../../common/experimental_features_service'); const dataFormattedForFieldBrowser = mockDataFormattedForFieldBrowser; @@ -104,7 +106,7 @@ describe('useHighlightedFields', () => { useHighlightedFields({ dataFormattedForFieldBrowser: dataFormattedForFieldBrowser.concat({ category: 'observer', - field: `observer.${SENTINEL_ONE_AGENT_ID_FIELD}`, + field: `observer.${RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one}`, values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'], originalValue: ['deb35a20-70f8-458e-a64a-c9e6f7575893'], isObjectArray: false, @@ -154,7 +156,7 @@ describe('useHighlightedFields', () => { }, { category: 'observer', - field: SENTINEL_ONE_AGENT_ID_FIELD, + field: RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one, values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'], originalValue: ['deb35a20-70f8-458e-a64a-c9e6f7575893'], isObjectArray: false, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.ts b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.ts index c60bb96c77974..571e01b9a2e22 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_highlighted_fields.ts @@ -8,15 +8,8 @@ import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import { find, isEmpty } from 'lodash/fp'; import { ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; -import { - CROWDSTRIKE_AGENT_ID_FIELD, - isAlertFromCrowdstrikeEvent, -} from '../../../../common/utils/crowdstrike_alert_check'; -import { - SENTINEL_ONE_AGENT_ID_FIELD, - isAlertFromSentinelOneEvent, -} from '../../../../common/utils/sentinelone_alert_check'; -import { isAlertFromEndpointEvent } from '../../../../common/utils/endpoint_alert_check'; +import { useAlertResponseActionsSupport } from '../../../../common/hooks/endpoint/use_alert_response_actions_support'; +import { isResponseActionsAlertAgentIdField } from '../../../../common/lib/endpoint'; import { getEventCategoriesFromData, getEventFieldsToDisplay, @@ -53,6 +46,7 @@ export const useHighlightedFields = ({ dataFormattedForFieldBrowser, investigationFields, }: UseHighlightedFieldsParams): UseHighlightedFieldsResult => { + const responseActionsSupport = useAlertResponseActionsSupport(dataFormattedForFieldBrowser); const eventCategories = getEventCategoriesFromData(dataFormattedForFieldBrowser); const eventCodeField = find( @@ -99,26 +93,12 @@ export const useHighlightedFields = ({ field.id = field.legacyId; } - // if the field is agent.id and the event is not an endpoint event we skip it - if ( - field.id === 'agent.id' && - !isAlertFromEndpointEvent({ data: dataFormattedForFieldBrowser }) - ) { - return acc; - } - - // if the field is observer.serial_number and the event is not a sentinel one event we skip it - if ( - field.id === SENTINEL_ONE_AGENT_ID_FIELD && - !isAlertFromSentinelOneEvent({ data: dataFormattedForFieldBrowser }) - ) { - return acc; - } - - // if the field is crowdstrike.event.DeviceId and the event is not a crowdstrike event we skip it + // If the field is one used by a supported Response Actions agentType, + // but the alert field is not the one that the agentType on the alert host uses, + // then exit and return accumulator if ( - field.id === CROWDSTRIKE_AGENT_ID_FIELD && - !isAlertFromCrowdstrikeEvent({ data: dataFormattedForFieldBrowser }) + isResponseActionsAlertAgentIdField(field.id) && + responseActionsSupport.details.agentIdField !== field.id ) { return acc; } diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx index 7334cf9d7e8f6..1b8897c73271b 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx @@ -10,7 +10,7 @@ import { EuiHealth } from '@elastic/eui'; import type { EntityTableRows } from '../../shared/components/entity_table/types'; import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; -import { EndpointAgentStatus } from '../../../../common/components/agents/agent_status'; +import { EndpointAgentStatus } from '../../../../common/components/endpoint/agents/agent_status'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; import type { HostItem } from '../../../../../common/search_strategy'; import { HostPolicyResponseActionStatus } from '../../../../../common/search_strategy'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/status_action.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/status_action.tsx index 3f4b46b318b82..7ea0986a3e721 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/status_action.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/status_action.tsx @@ -19,7 +19,7 @@ import type { CommandExecutionComponentProps } from '../../console/types'; import { FormattedError } from '../../formatted_error'; import { ConsoleCodeBlock } from '../../console/components/console_code_block'; import { POLICY_STATUS_TO_TEXT } from '../../../pages/endpoint_hosts/view/host_constants'; -import { getAgentStatusText } from '../../../../common/components/agents/agent_status_text'; +import { getAgentStatusText } from '../../../../common/components/endpoint/agents/agent_status_text'; export const EndpointStatusActionResult = memo< CommandExecutionComponentProps< diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/agent_info/agent_info.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/agent_info/agent_info.tsx index 4c0bf3ca511a2..7845b9d8b3efd 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/agent_info/agent_info.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/agent_info/agent_info.tsx @@ -6,7 +6,7 @@ */ import React, { memo } from 'react'; -import { AgentStatus } from '../../../../../../common/components/agents/agent_status'; +import { AgentStatus } from '../../../../../../common/components/endpoint/agents/agent_status'; import { useAgentStatusHook } from '../../../../../hooks/agents/use_get_agent_status'; import type { ThirdPartyAgentInfo } from '../../../../../../../common/types'; import { HeaderAgentInfo } from '../header_agent_info'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx index e9d73b3d62d63..28ac70e7c969d 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx @@ -7,7 +7,7 @@ import React, { memo } from 'react'; import { EuiSkeletonText } from '@elastic/eui'; -import { EndpointAgentStatus } from '../../../../../../common/components/agents/agent_status'; +import { EndpointAgentStatus } from '../../../../../../common/components/endpoint/agents/agent_status'; import { HeaderAgentInfo } from '../header_agent_info'; import { useGetEndpointDetails } from '../../../../../hooks'; import type { Platform } from '../platforms'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/sentinel_one/header_sentinel_one_info.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/sentinel_one/header_sentinel_one_info.tsx index 212f66b6fe6e6..72a155833f967 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/sentinel_one/header_sentinel_one_info.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/sentinel_one/header_sentinel_one_info.tsx @@ -6,7 +6,7 @@ */ import React, { memo } from 'react'; -import { AgentStatus } from '../../../../../../common/components/agents/agent_status'; +import { AgentStatus } from '../../../../../../common/components/endpoint/agents/agent_status'; import { useAgentStatusHook } from '../../../../../hooks/agents/use_get_agent_status'; import { useIsExperimentalFeatureEnabled } from '../../../../../../common/hooks/use_experimental_features'; import type { ThirdPartyAgentInfo } from '../../../../../../../common/types'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/offline_callout.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/offline_callout.tsx index d18a8526fb3eb..727d30a6c75b4 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/offline_callout.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/offline_callout.tsx @@ -9,6 +9,7 @@ import React, { memo, useMemo } from 'react'; import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { isAgentTypeAndActionSupported } from '../../../../common/lib/endpoint'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useAgentStatusHook } from '../../../hooks/agents/use_get_agent_status'; import type { ResponseActionAgentType } from '../../../../../common/endpoint/service/response_actions/constants'; @@ -27,16 +28,10 @@ export const OfflineCallout = memo(({ agentType, endpointId const isCrowdstrikeAgent = agentType === 'crowdstrike'; const getAgentStatus = useAgentStatusHook(); const agentStatusClientEnabled = useIsExperimentalFeatureEnabled('agentStatusClientEnabled'); - const isSentinelOneV1Enabled = useIsExperimentalFeatureEnabled( - 'responseActionsSentinelOneV1Enabled' - ); - const sentinelOneManualHostActionsEnabled = useIsExperimentalFeatureEnabled( - 'sentinelOneManualHostActionsEnabled' - ); - const crowdstrikeManualHostActionsEnabled = useIsExperimentalFeatureEnabled( - 'responseActionsCrowdstrikeManualHostIsolationEnabled' - ); + const isAgentTypeEnabled = useMemo(() => { + return isAgentTypeAndActionSupported(agentType); + }, [agentType]); const { data: endpointDetails } = useGetEndpointDetails(endpointId, { refetchInterval: 10000, @@ -45,9 +40,7 @@ export const OfflineCallout = memo(({ agentType, endpointId const { data } = getAgentStatus([endpointId], agentType, { enabled: - (sentinelOneManualHostActionsEnabled && isSentinelOneAgent) || - (crowdstrikeManualHostActionsEnabled && isCrowdstrikeAgent) || - (isEndpointAgent && agentStatusClientEnabled), + (isEndpointAgent && agentStatusClientEnabled) || (!isEndpointAgent && isAgentTypeEnabled), }); const showOfflineCallout = useMemo( () => @@ -64,11 +57,7 @@ export const OfflineCallout = memo(({ agentType, endpointId ] ); - if ( - (isEndpointAgent && !endpointDetails) || - (isSentinelOneV1Enabled && isSentinelOneAgent && !data) || - (crowdstrikeManualHostActionsEnabled && isCrowdstrikeAgent && !data) - ) { + if ((isEndpointAgent && !endpointDetails) || (isAgentTypeEnabled && !data)) { return null; } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts index 22459383fde8f..84624c2ce595b 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { isActionSupportedByAgentType } from '../../../../../common/endpoint/service/response_actions/is_response_action_supported'; +import { isAgentTypeAndActionSupported } from '../../../../common/lib/endpoint'; import { getRbacControl } from '../../../../../common/endpoint/service/response_actions/utils'; import { UploadActionResult } from '../command_render_components/upload_action'; import { ArgumentFileSelector } from '../../console_argument_selectors'; @@ -139,6 +139,7 @@ const COMMENT_ARG_ABOUT = i18n.translate( export interface GetEndpointConsoleCommandsOptions { endpointAgentId: string; agentType: ResponseActionAgentType; + /** Applicable only for Endpoint Agents */ endpointCapabilities: ImmutableArray; endpointPrivileges: EndpointPrivileges; } @@ -556,43 +557,30 @@ export const getEndpointConsoleCommands = ({ } }; +/** @private */ +const disableCommand = (command: CommandDefinition, agentType: ResponseActionAgentType) => { + command.helpDisabled = true; + command.helpHidden = true; + command.validate = () => + UPGRADE_AGENT_FOR_RESPONDER(agentType, command.name as ConsoleResponseActionCommands); +}; + /** @private */ const adjustCommandsForSentinelOne = ({ commandList, }: { commandList: CommandDefinition[]; }): CommandDefinition[] => { - const featureFlags = ExperimentalFeaturesService.get(); - const isHostIsolationEnabled = featureFlags.responseActionsSentinelOneV1Enabled; - const isGetFileFeatureEnabled = featureFlags.responseActionsSentinelOneGetFileEnabled; - - const disableCommand = (command: CommandDefinition) => { - command.helpDisabled = true; - command.helpHidden = true; - command.validate = () => - UPGRADE_AGENT_FOR_RESPONDER('sentinel_one', command.name as ConsoleResponseActionCommands); - }; - return commandList.map((command) => { - const agentSupportsResponseAction = - command.name === 'status' - ? false - : isActionSupportedByAgentType( - 'sentinel_one', - RESPONSE_CONSOLE_COMMAND_TO_API_COMMAND_MAP[ - command.name as ConsoleResponseActionCommands - ], - 'manual' - ); - - // If command is not supported by SentinelOne - disable it if ( - !agentSupportsResponseAction || - (command.name === 'get-file' && !isGetFileFeatureEnabled) || - (command.name === 'isolate' && !isHostIsolationEnabled) || - (command.name === 'release' && !isHostIsolationEnabled) + command.name === 'status' || + !isAgentTypeAndActionSupported( + 'sentinel_one', + RESPONSE_CONSOLE_COMMAND_TO_API_COMMAND_MAP[command.name as ConsoleResponseActionCommands], + 'manual' + ) ) { - disableCommand(command); + disableCommand(command, 'sentinel_one'); } return command; @@ -605,35 +593,16 @@ const adjustCommandsForCrowdstrike = ({ }: { commandList: CommandDefinition[]; }): CommandDefinition[] => { - const featureFlags = ExperimentalFeaturesService.get(); - const isHostIsolationEnabled = featureFlags.responseActionsCrowdstrikeManualHostIsolationEnabled; - - const disableCommand = (command: CommandDefinition) => { - command.helpDisabled = true; - command.helpHidden = true; - command.validate = () => - UPGRADE_AGENT_FOR_RESPONDER('crowdstrike', command.name as ConsoleResponseActionCommands); - }; - return commandList.map((command) => { - const agentSupportsResponseAction = - command.name === 'status' - ? false - : isActionSupportedByAgentType( - 'crowdstrike', - RESPONSE_CONSOLE_COMMAND_TO_API_COMMAND_MAP[ - command.name as ConsoleResponseActionCommands - ], - 'manual' - ); - - // If command is not supported by Crowdstrike - disable it if ( - !agentSupportsResponseAction || - (command.name === 'isolate' && !isHostIsolationEnabled) || - (command.name === 'release' && !isHostIsolationEnabled) + command.name === 'status' || + !isAgentTypeAndActionSupported( + 'crowdstrike', + RESPONSE_CONSOLE_COMMAND_TO_API_COMMAND_MAP[command.name as ConsoleResponseActionCommands], + 'manual' + ) ) { - disableCommand(command); + disableCommand(command, 'crowdstrike'); } return command; diff --git a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_endpoint_pending_actions_summary.ts b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_endpoint_pending_actions_summary.ts index cee29041b0354..57f0150317f5d 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_endpoint_pending_actions_summary.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_endpoint_pending_actions_summary.ts @@ -9,7 +9,7 @@ import type { QueryObserverResult, UseQueryOptions } from '@tanstack/react-query import { useQuery } from '@tanstack/react-query'; import type { IHttpFetchError } from '@kbn/core-http-browser'; import type { PendingActionsResponse } from '../../../../common/endpoint/types'; -import { fetchPendingActionsByAgentId } from '../../../common/lib/endpoint_pending_actions'; +import { fetchPendingActionsByAgentId } from '../../../common/lib/endpoint/endpoint_pending_actions'; /** * Retrieves the pending actions against the given Endpoint `agent.id`'s diff --git a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_isolate_endpoint_request.ts b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_isolate_endpoint_request.ts index b0fb5029ab15d..b4cb131f6ae9c 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_isolate_endpoint_request.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_isolate_endpoint_request.ts @@ -8,7 +8,7 @@ import type { UseMutationOptions, UseMutationResult } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query'; import type { IHttpFetchError } from '@kbn/core-http-browser'; -import { isolateHost } from '../../../common/lib/endpoint_isolation'; +import { isolateHost } from '../../../common/lib/endpoint/endpoint_isolation'; import type { HostIsolationRequestBody, ResponseActionApiResponse, diff --git a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_release_endpoint_request.ts b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_release_endpoint_request.ts index f6d45393ae885..b9e140dc3ba9d 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_release_endpoint_request.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_send_release_endpoint_request.ts @@ -12,7 +12,7 @@ import type { HostIsolationRequestBody, ResponseActionApiResponse, } from '../../../../common/endpoint/types'; -import { unIsolateHost } from '../../../common/lib/endpoint_isolation'; +import { unIsolateHost } from '../../../common/lib/endpoint/endpoint_isolation'; /** * Create host release requests diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts index 7030f13bdd0f9..c3cc8adc3b4fe 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts @@ -23,8 +23,8 @@ import { HOST_METADATA_LIST_ROUTE, METADATA_TRANSFORMS_STATUS_ROUTE, } from '../../../../common/endpoint/constants'; -import type { PendingActionsHttpMockInterface } from '../../../common/lib/endpoint_pending_actions/mocks'; -import { pendingActionsHttpMock } from '../../../common/lib/endpoint_pending_actions/mocks'; +import type { PendingActionsHttpMockInterface } from '../../../common/lib/endpoint/endpoint_pending_actions/mocks'; +import { pendingActionsHttpMock } from '../../../common/lib/endpoint/endpoint_pending_actions/mocks'; import { TRANSFORM_STATES } from '../../../../common/constants'; import type { TransformStatsResponse } from './types'; import type { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts index ca1b0dfb56fea..763bc15dace43 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts @@ -39,7 +39,7 @@ import { hostIsolationHttpMocks, hostIsolationRequestBodyMock, hostIsolationResponseMock, -} from '../../../../common/lib/endpoint_isolation/mocks'; +} from '../../../../common/lib/endpoint/endpoint_isolation/mocks'; import { endpointPageHttpMock, failedTransformStateMock } from '../mocks'; import { HOST_METADATA_LIST_ROUTE } from '../../../../../common/endpoint/constants'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts index f8ffb703fb72e..215a789a8b4ed 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts @@ -29,8 +29,8 @@ import type { MetadataListResponse, ResponseActionApiResponse, } from '../../../../../common/endpoint/types'; -import { isolateHost, unIsolateHost } from '../../../../common/lib/endpoint_isolation'; -import { fetchPendingActionsByAgentId } from '../../../../common/lib/endpoint_pending_actions'; +import { isolateHost, unIsolateHost } from '../../../../common/lib/endpoint/endpoint_isolation'; +import { fetchPendingActionsByAgentId } from '../../../../common/lib/endpoint/endpoint_pending_actions'; import type { ImmutableMiddlewareAPI, ImmutableMiddlewareFactory } from '../../../../common/store'; import type { AppAction } from '../../../../common/store/actions'; import { sendGetEndpointSpecificPackagePolicies } from '../../../services/policies/policies'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts index 1bc156d0c5a37..a851d2273907d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts @@ -29,7 +29,7 @@ import { INGEST_API_PACKAGE_POLICIES, } from '../../../services/policies/ingest'; import type { GetPolicyListResponse } from '../../policy/types'; -import { pendingActionsResponseMock } from '../../../../common/lib/endpoint_pending_actions/mocks'; +import { pendingActionsResponseMock } from '../../../../common/lib/endpoint/endpoint_pending_actions/mocks'; import { ACTION_STATUS_ROUTE, ENDPOINT_DEFAULT_SORT_DIRECTION, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx index 60ccec200d3c8..0140cba0780ed 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx @@ -21,7 +21,7 @@ import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use import { AgentStatus, EndpointAgentStatus, -} from '../../../../../common/components/agents/agent_status'; +} from '../../../../../common/components/endpoint/agents/agent_status'; import { isPolicyOutOfDate } from '../../utils'; import type { HostInfo } from '../../../../../../common/endpoint/types'; import { useEndpointSelector } from '../hooks'; 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 75aeaf45a9a8a..abda617e2a779 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 @@ -20,7 +20,6 @@ import { agentPolicies, uiQueryParams } from '../../store/selectors'; import { useAppUrl } from '../../../../../common/lib/kibana/hooks'; import type { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router'; import { isEndpointHostIsolated } from '../../../../../common/utils/validators'; -import { isIsolationSupported } from '../../../../../../common/endpoint/service/host_isolation/utils'; interface Options { isEndpointList: boolean; @@ -59,11 +58,6 @@ export const useEndpointActionItems = ( const endpointPolicyId = endpointMetadata.Endpoint.policy.applied.id; const endpointHostName = endpointMetadata.host.hostname; const fleetAgentId = endpointMetadata.elastic.agent.id; - const isolationSupported = isIsolationSupported({ - osName: endpointMetadata.host.os.name, - version: endpointMetadata.agent.version, - capabilities: endpointMetadata.Endpoint.capabilities, - }); const { show, selected_endpoint: _selectedEndpoint, ...currentUrlParams } = allCurrentUrlParams; const endpointActionsPath = getEndpointDetailsPath({ name: 'endpointActivityLog', @@ -101,7 +95,7 @@ export const useEndpointActionItems = ( /> ), }); - } else if (isolationSupported && canIsolateHost) { + } else if (canIsolateHost) { // For Platinum++ licenses, users also have ability to isolate isolationActions.push({ 'data-test-subj': 'isolateLink', diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 06029b8a64668..ceb9f1ce10e86 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -25,7 +25,7 @@ import { POLICY_STATUS_TO_HEALTH_COLOR, POLICY_STATUS_TO_TEXT } from './host_con import { mockPolicyResultList } from '../../policy/store/test_mock_utils'; import { getEndpointDetailsPath } from '../../../common/routing'; import { KibanaServices, useKibana, useToasts, useUiSetting$ } from '../../../../common/lib/kibana'; -import { hostIsolationHttpMocks } from '../../../../common/lib/endpoint_isolation/mocks'; +import { hostIsolationHttpMocks } from '../../../../common/lib/endpoint/endpoint_isolation/mocks'; import { isFailedResourceState, isLoadedResourceState, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 440ad6a7560a6..89473ece661a3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -39,7 +39,7 @@ import { EndpointListNavLink } from './components/endpoint_list_nav_link'; import { AgentStatus, EndpointAgentStatus, -} from '../../../../common/components/agents/agent_status'; +} from '../../../../common/components/endpoint/agents/agent_status'; import { EndpointDetailsFlyout } from './details'; import * as selectors from '../store/selectors'; import { getEndpointPendingActionsCallback } from '../store/selectors'; diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx index ea6639ac8bcbf..99eb2ed17e6b6 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx @@ -13,7 +13,7 @@ import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_ex import { AgentStatus, EndpointAgentStatus, -} from '../../../../common/components/agents/agent_status'; +} from '../../../../common/components/endpoint/agents/agent_status'; import { OverviewDescriptionList } from '../../../../common/components/overview_description_list'; import type { DescriptionList } from '../../../../../common/utility_types'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/back_to_alert_details_link.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/back_to_alert_details_link.tsx index 6ae4207a46f78..d14622cc0e7d0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/back_to_alert_details_link.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/back_to_alert_details_link.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { ISOLATE_HOST, UNISOLATE_HOST, -} from '../../../../../detections/components/host_isolation/translations'; +} from '../../../../../common/components/endpoint/host_isolation'; import { ALERT_DETAILS, TECHNICAL_PREVIEW, TECHNICAL_PREVIEW_DESCRIPTION } from '../translations'; const BackToAlertDetailsLinkComponent = ({ diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/body.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/body.tsx index 446aa27f5a3a5..5aea7657f8d61 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/body.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/body.tsx @@ -9,8 +9,10 @@ import { EuiFlyoutBody } from '@elastic/eui'; import styled from 'styled-components'; import React from 'react'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -import { EndpointIsolateSuccess } from '../../../../../common/components/endpoint/host_isolation'; -import { HostIsolationPanel } from '../../../../../detections/components/host_isolation'; +import { + HostIsolationPanel, + EndpointIsolateSuccess, +} from '../../../../../common/components/endpoint/host_isolation'; import type { BrowserFields, TimelineEventsDetailsItem, diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.test.tsx index e48dbe5215f39..a269dd422ca38 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.test.tsx @@ -37,14 +37,11 @@ const mockAlertDetailsDataWithIsObject = mockAlertDetailsData.map((detail) => { }; }) as TimelineEventsDetailsItem[]; -jest.mock('../../../../../../common/endpoint/service/host_isolation/utils', () => { - return { - isIsolationSupported: jest.fn().mockReturnValue(true), - }; -}); +jest.mock('../../../../../common/components/endpoint/host_isolation'); +jest.mock('../../../../../common/components/endpoint/responder'); jest.mock( - '../../../../../detections/containers/detection_engine/alerts/use_host_isolation_status', + '../../../../../common/components/endpoint/host_isolation/from_alerts/use_host_isolation_status', () => { return { useEndpointHostIsolationStatus: jest.fn().mockReturnValue({ @@ -74,16 +71,6 @@ jest.mock( ); jest.mock('../../../../../cases/components/use_insert_timeline'); -jest.mock('../../../../../common/utils/endpoint_alert_check', () => { - const realEndpointAlertCheckUtils = jest.requireActual( - '../../../../../common/utils/endpoint_alert_check' - ); - return { - isTimelineEventItemAnAlert: realEndpointAlertCheckUtils.isTimelineEventItemAnAlert, - isAlertFromEndpointAlert: jest.fn().mockReturnValue(true), - isAlertFromEndpointEvent: jest.fn().mockReturnValue(true), - }; -}); jest.mock( '../../../../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.tsx index ea0df8fd3c684..61dde196c6eda 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/footer.tsx @@ -9,6 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiFlyoutFooter, EuiFlexGroup, EuiFlexItem, useEuiTheme } from '@elastic/eui'; import { find } from 'lodash/fp'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; +import { getAlertDetailsFieldValue } from '../../../../../common/lib/endpoint/utils/get_event_details_field_values'; import { isActiveTimeline } from '../../../../../helpers'; import { TakeActionDropdown } from '../../../../../detections/components/take_action_dropdown'; import type { TimelineEventsDetailsItem } from '../../../../../../common/search_strategy'; @@ -16,7 +17,6 @@ import { useExceptionFlyout } from '../../../../../detections/components/alerts_ import { AddExceptionFlyoutWrapper } from '../../../../../detections/components/alerts_table/timeline_actions/alert_context_menu'; import { EventFiltersFlyout } from '../../../../../management/pages/event_filters/view/components/event_filters_flyout'; import { useEventFilterModal } from '../../../../../detections/components/alerts_table/timeline_actions/use_event_filter_modal'; -import { getFieldValue } from '../../../../../detections/components/host_isolation/helpers'; import type { Status } from '../../../../../../common/api/detection_engine'; import { OsqueryFlyout } from '../../../../../detections/components/osquery/osquery_flyout'; import { useRefetchByScope } from './use_refetch_by_scope'; @@ -93,7 +93,10 @@ export const FlyoutFooterComponent = ({ ].reduce( (acc, curr) => ({ ...acc, - [curr.name]: getFieldValue({ category: curr.category, field: curr.field }, detailsData), + [curr.name]: getAlertDetailsFieldValue( + { category: curr.category, field: curr.field }, + detailsData + ), }), {} as AddExceptionModalWrapperData ), diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/header.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/header.tsx index 0d139449b1ca2..206d35e187cf6 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/header.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/header.tsx @@ -8,10 +8,10 @@ import { EuiFlyoutHeader } from '@elastic/eui'; import React, { useMemo } from 'react'; -import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../../common/utils/sentinelone_alert_check'; import type { GetFieldsData } from '../../../../../common/hooks/use_get_fields_data'; import { ExpandableEventTitle } from '../expandable_event'; import { BackToAlertDetailsLink } from './back_to_alert_details_link'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../../../common/endpoint/service/response_actions/constants'; interface FlyoutHeaderComponentProps { eventId: string; @@ -45,7 +45,7 @@ const FlyoutHeaderContentComponent = ({ getFieldsData, }: FlyoutHeaderComponentProps) => { const isSentinelOneAlert = useMemo( - () => !!(isAlert && getFieldsData(SENTINEL_ONE_AGENT_ID_FIELD)?.length), + () => !!(isAlert && getFieldsData(RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one)?.length), [getFieldsData, isAlert] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx index 31491730adc83..acfdde85b6826 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx @@ -7,8 +7,8 @@ import { some } from 'lodash/fp'; import { useMemo } from 'react'; +import { getAlertDetailsFieldValue } from '../../../../common/lib/endpoint/utils/get_event_details_field_values'; import type { TimelineEventsDetailsItem } from '../../../../../common/search_strategy'; -import { getFieldValue } from '../../../../detections/components/host_isolation/helpers'; import { DEFAULT_ALERTS_INDEX, DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants'; export interface GetBasicDataFromDetailsData { @@ -34,50 +34,57 @@ export const useBasicDataFromDetailsData = ( const ruleId = useMemo( () => isAlert - ? getFieldValue({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, data) - : getFieldValue({ category: 'signal', field: 'signal.rule.id' }, data), + ? getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, data) + : getAlertDetailsFieldValue({ category: 'signal', field: 'signal.rule.id' }, data), [isAlert, data] ); const ruleName = useMemo( - () => getFieldValue({ category: 'kibana', field: 'kibana.alert.rule.name' }, data), + () => getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.rule.name' }, data), [data] ); const ruleDescription = useMemo( - () => getFieldValue({ category: 'kibana', field: 'kibana.alert.rule.description' }, data), + () => + getAlertDetailsFieldValue( + { category: 'kibana', field: 'kibana.alert.rule.description' }, + data + ), [data] ); - const alertId = useMemo(() => getFieldValue({ category: '_id', field: '_id' }, data), [data]); + const alertId = useMemo( + () => getAlertDetailsFieldValue({ category: '_id', field: '_id' }, data), + [data] + ); const indexName = useMemo( - () => getFieldValue({ category: '_index', field: '_index' }, data), + () => getAlertDetailsFieldValue({ category: '_index', field: '_index' }, data), [data] ); const alertUrl = useMemo( - () => getFieldValue({ category: 'kibana', field: 'kibana.alert.url' }, data), + () => getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.url' }, data), [data] ); const agentId = useMemo( - () => getFieldValue({ category: 'agent', field: 'agent.id' }, data), + () => getAlertDetailsFieldValue({ category: 'agent', field: 'agent.id' }, data), [data] ); const hostName = useMemo( - () => getFieldValue({ category: 'host', field: 'host.name' }, data), + () => getAlertDetailsFieldValue({ category: 'host', field: 'host.name' }, data), [data] ); const userName = useMemo( - () => getFieldValue({ category: 'user', field: 'user.name' }, data), + () => getAlertDetailsFieldValue({ category: 'user', field: 'user.name' }, data), [data] ); const timestamp = useMemo( - () => getFieldValue({ category: 'base', field: '@timestamp' }, data), + () => getAlertDetailsFieldValue({ category: 'base', field: '@timestamp' }, data), [data] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx index 0f186fdcf39d9..edf2da964b2b3 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.test.tsx @@ -46,18 +46,12 @@ jest.mock('react-router-dom', () => { }; }); -jest.mock('../../../../../common/endpoint/service/host_isolation/utils', () => { - return { - isIsolationSupported: jest.fn().mockReturnValue(true), - }; -}); - jest.mock('../../../../common/hooks/use_space_id', () => ({ useSpaceId: jest.fn().mockReturnValue('testSpace'), })); jest.mock( - '../../../../detections/containers/detection_engine/alerts/use_host_isolation_status', + '../../../../common/components/endpoint/host_isolation/from_alerts/use_host_isolation_status', () => { return { useEndpointHostIsolationStatus: jest.fn().mockReturnValue({ @@ -97,12 +91,6 @@ jest.mock( ); jest.mock('../../../../cases/components/use_insert_timeline'); -jest.mock('../../../../common/utils/endpoint_alert_check', () => { - return { - isAlertFromEndpointAlert: jest.fn().mockReturnValue(true), - isAlertFromEndpointEvent: jest.fn().mockReturnValue(true), - }; -}); jest.mock( '../../../../detections/components/alerts_table/timeline_actions/use_investigate_in_timeline', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx index 49945e07796fa..0982d829e8886 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx @@ -25,8 +25,10 @@ import { useHostIsolationTools } from './use_host_isolation_tools'; import { FlyoutBody, FlyoutHeader, FlyoutFooter } from './flyout'; import { useBasicDataFromDetailsData, getAlertIndexAlias } from './helpers'; import { useSpaceId } from '../../../../common/hooks/use_space_id'; -import { EndpointIsolateSuccess } from '../../../../common/components/endpoint/host_isolation'; -import { HostIsolationPanel } from '../../../../detections/components/host_isolation'; +import { + EndpointIsolateSuccess, + HostIsolationPanel, +} from '../../../../common/components/endpoint/host_isolation'; import { ALERT_SUMMARY_CONVERSATION_ID, ALERT_SUMMARY_CONTEXT_DESCRIPTION, diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/use_host_isolation_tools.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/use_host_isolation_tools.tsx index 5667c4e0a6156..7885e1cd542dc 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/use_host_isolation_tools.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/use_host_isolation_tools.tsx @@ -7,7 +7,7 @@ import { useCallback, useMemo, useReducer } from 'react'; -import { useWithCaseDetailsRefresh } from '../../../../common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context'; +import { useWithCaseDetailsRefresh } from '../../../../common/components/endpoint/host_isolation/from_cases/endpoint_host_isolation_cases_context'; interface HostIsolationStateReducer { isolateAction: 'isolateHost' | 'unisolateHost'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx index 46a3301d52569..28b60305b3f23 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx @@ -19,11 +19,10 @@ import { ALERT_HOST_CRITICALITY, ALERT_USER_CRITICALITY, } from '../../../../../../common/field_maps/field_names'; -import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../../common/utils/sentinelone_alert_check'; import { AgentStatus, EndpointAgentStatusById, -} from '../../../../../common/components/agents/agent_status'; +} from '../../../../../common/components/endpoint/agents/agent_status'; import { INDICATOR_REFERENCE } from '../../../../../../common/cti/constants'; import { DefaultDraggable } from '../../../../../common/components/draggables'; import { Bytes, BYTES_FORMAT } from './bytes'; @@ -54,6 +53,7 @@ import { RuleStatus } from './rule_status'; import { HostName } from './host_name'; import { UserName } from './user_name'; import { AssetCriticalityLevel } from './asset_criticality_level'; +import { RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD } from '../../../../../../common/endpoint/service/response_actions/constants'; // simple black-list to prevent dragging and dropping fields such as message name const columnNamesNotDraggable = [MESSAGE_FIELD_NAME]; @@ -276,7 +276,7 @@ const FormattedFieldValueComponent: React.FC<{ ); } else if ( fieldName === AGENT_STATUS_FIELD_NAME && - fieldFromBrowserField?.name === SENTINEL_ONE_AGENT_ID_FIELD + fieldFromBrowserField?.name === RESPONSE_ACTIONS_ALERT_AGENT_ID_FIELD.sentinel_one ) { return ; } else if (fieldName === ALERT_HOST_CRITICALITY || fieldName === ALERT_USER_CRITICALITY) { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 673bfbcfe49ff..7305a2ca70a1d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -36143,8 +36143,6 @@ "xpack.securitySolution.flyout.entityDetails.userDetails.tableTabLabel": "Tableau", "xpack.securitySolution.flyout.entityDetails.userDetails.tabsLegend": "Onglets des documents de ressources", "xpack.securitySolution.flyout.entityDetails.valuesColumnTitle": "Valeurs", - "xpack.securitySolution.flyout.isolateHost.isolateTitle": "Isoler l'hôte", - "xpack.securitySolution.flyout.isolateHost.releaseTitle": "Libérer l'hôte", "xpack.securitySolution.flyout.left.insights.buttonGroupLegendLabel": "Options des informations exploitables", "xpack.securitySolution.flyout.left.insights.correlations.ancestryAlertsNoDataDescription": "Aucune alerte associée par ancêtre.", "xpack.securitySolution.flyout.left.insights.correlations.nameColumnLabel": "Nom", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 56df15a9c73bd..2c6f6ea67b15e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -36118,8 +36118,6 @@ "xpack.securitySolution.flyout.entityDetails.userDetails.tableTabLabel": "表", "xpack.securitySolution.flyout.entityDetails.userDetails.tabsLegend": "アセットドキュメントタブ", "xpack.securitySolution.flyout.entityDetails.valuesColumnTitle": "値", - "xpack.securitySolution.flyout.isolateHost.isolateTitle": "ホストの分離", - "xpack.securitySolution.flyout.isolateHost.releaseTitle": "ホストのリリース", "xpack.securitySolution.flyout.left.insights.buttonGroupLegendLabel": "インサイトオプション", "xpack.securitySolution.flyout.left.insights.correlations.ancestryAlertsNoDataDescription": "上位項目に関連するアラートはありません。", "xpack.securitySolution.flyout.left.insights.correlations.nameColumnLabel": "名前", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 48d126c33a1e9..66f2bb582b4be 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -36161,8 +36161,6 @@ "xpack.securitySolution.flyout.entityDetails.userDetails.tableTabLabel": "表", "xpack.securitySolution.flyout.entityDetails.userDetails.tabsLegend": "资产文档选项卡", "xpack.securitySolution.flyout.entityDetails.valuesColumnTitle": "值", - "xpack.securitySolution.flyout.isolateHost.isolateTitle": "隔离主机", - "xpack.securitySolution.flyout.isolateHost.releaseTitle": "释放主机", "xpack.securitySolution.flyout.left.insights.buttonGroupLegendLabel": "洞见选项", "xpack.securitySolution.flyout.left.insights.correlations.ancestryAlertsNoDataDescription": "无告警与体系相关。", "xpack.securitySolution.flyout.left.insights.correlations.nameColumnLabel": "名称", diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts index c7b54e26db890..2d0d80af9c242 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts @@ -41,6 +41,7 @@ import { DOCUMENT_DETAILS_FLYOUT_JSON_TAB, DOCUMENT_DETAILS_FLYOUT_OVERVIEW_TAB, DOCUMENT_DETAILS_FLYOUT_TABLE_TAB, + DOCUMENT_DETAILS_FLYOUT_FOOTER_ISOLATE_HOST, } from '../../../../screens/expandable_flyout/alert_details_right_panel'; import { closeFlyout, @@ -200,10 +201,10 @@ describe('Alert details expandable flyout right panel', { tags: ['@ess', '@serve // cy.log('should isolate host'); - // TODO figure out why isolate host isn't showing up in the dropdown + // TODO this will change when respond is improved // https://github.com/elastic/security-team/issues/6302 - // openTakeActionButton(); - // cy.get(DOCUMENT_DETAILS_FLYOUT_FOOTER_ISOLATE_HOST).should('be.visible'); + openTakeActionButton(); + cy.get(DOCUMENT_DETAILS_FLYOUT_FOOTER_ISOLATE_HOST).should('be.disabled'); cy.log('should respond'); @@ -214,6 +215,7 @@ describe('Alert details expandable flyout right panel', { tags: ['@ess', '@serve cy.log('should investigate in timeline'); + openTakeActionButton(); selectTakeActionItem(DOCUMENT_DETAILS_FLYOUT_FOOTER_INVESTIGATE_IN_TIMELINE); cy.get(DOCUMENT_DETAILS_FLYOUT_FOOTER_INVESTIGATE_IN_TIMELINE_SECTION) .first() From ab21d4fee4f5e9149b85b1a0ce7fc0dbcfaa5062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Tue, 18 Jun 2024 14:23:16 +0200 Subject: [PATCH 045/127] [EBT] Combine packages (#186048) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 6 +- package.json | 6 +- packages/analytics/README.md | 11 - packages/analytics/ebt/README.md | 11 + packages/analytics/{ => ebt}/client/README.md | 6 +- packages/analytics/{ => ebt}/client/index.ts | 1 + .../analytics_client/analytics_client.test.ts | 788 +++++++++--------- .../src/analytics_client/analytics_client.ts | 0 .../analytics_client/context_service.test.ts | 0 .../src/analytics_client/context_service.ts | 0 .../client/src/analytics_client/index.ts | 0 .../client/src/analytics_client/mocks.ts | 0 .../analytics_client/opt_in_config.test.ts | 0 .../src/analytics_client/opt_in_config.ts | 0 .../shippers_registry.test.ts | 0 .../src/analytics_client/shippers_registry.ts | 0 .../client/src/analytics_client/types.ts | 0 .../{ => ebt}/client/src/events/index.ts | 0 .../{ => ebt}/client/src/events/types.ts | 0 .../analytics/{ => ebt}/client/src/mocks.ts | 0 .../{ => ebt}/client/src/schema/index.ts | 0 .../{ => ebt}/client/src/schema/types.test.ts | 0 .../{ => ebt}/client/src/schema/types.ts | 0 .../src/schema/validation/excess.test.ts | 0 .../client/src/schema/validation/excess.ts | 0 .../client/src/schema/validation/index.ts | 0 .../schema/validation/schema_to_io_ts.test.ts | 0 .../src/schema/validation/schema_to_io_ts.ts | 0 .../schema/validation/validate_schema.test.ts | 0 .../src/schema/validation/validate_schema.ts | 0 .../{ => ebt}/client/src/shippers/index.ts | 0 .../{ => ebt}/client/src/shippers/mocks.ts | 0 .../{ => ebt}/client/src/shippers/types.ts | 0 packages/analytics/ebt/index.ts | 57 ++ .../analytics/{client => ebt}/jest.config.js | 6 +- .../analytics/{client => ebt}/kibana.jsonc | 2 +- .../analytics/{client => ebt}/package.json | 3 +- .../analytics/{ => ebt}/shippers/README.md | 2 +- .../shippers/elastic_v3/browser/README.md | 8 +- .../shippers/elastic_v3/browser/index.ts | 2 +- .../browser/src/browser_shipper.test.ts | 284 +++---- .../elastic_v3/browser/src/browser_shipper.ts | 11 +- .../shippers/elastic_v3/common/README.md | 4 +- .../shippers/elastic_v3/common/index.ts | 0 .../common/src/build_headers.test.ts | 0 .../elastic_v3/common/src/build_headers.ts | 0 .../elastic_v3/common/src/build_url.test.ts | 0 .../elastic_v3/common/src/build_url.ts | 0 .../common/src/error_with_code.test.ts | 0 .../elastic_v3/common/src/error_with_code.ts | 0 .../common/src/events_to_ndjson.test.ts | 2 +- .../elastic_v3/common/src/events_to_ndjson.ts | 2 +- .../src/report_telemetry_counters.test.ts | 2 +- .../common/src/report_telemetry_counters.ts | 2 +- .../shippers/elastic_v3/common/src/types.ts | 0 .../shippers/elastic_v3/server/README.md | 8 +- .../shippers/elastic_v3/server/index.ts | 2 +- .../server/src/server_shipper.test.mocks.ts | 0 .../server/src/server_shipper.test.ts | 571 +++++++++++++ .../elastic_v3/server/src/server_shipper.ts | 16 +- .../{ => ebt}/shippers/fullstory/README.md | 6 +- .../{ => ebt}/shippers/fullstory/index.ts | 0 .../fullstory/src/format_payload.test.ts | 0 .../shippers/fullstory/src/format_payload.ts | 0 .../src/fullstory_shipper.test.mocks.ts | 0 .../fullstory/src/fullstory_shipper.test.ts | 0 .../fullstory/src/fullstory_shipper.ts | 11 +- .../fullstory/src/get_parsed_version.test.ts | 0 .../fullstory/src/get_parsed_version.ts | 0 .../fullstory/src/load_snippet.test.ts | 24 +- .../shippers/fullstory/src/load_snippet.ts | 0 .../{ => ebt}/shippers/fullstory/src/types.ts | 0 .../analytics/{client => ebt}/tsconfig.json | 15 +- .../elastic_v3/browser/jest.config.js | 13 - .../shippers/elastic_v3/browser/kibana.jsonc | 5 - .../shippers/elastic_v3/browser/package.json | 7 - .../shippers/elastic_v3/browser/tsconfig.json | 21 - .../shippers/elastic_v3/common/jest.config.js | 13 - .../shippers/elastic_v3/common/kibana.jsonc | 5 - .../shippers/elastic_v3/common/package.json | 7 - .../shippers/elastic_v3/common/tsconfig.json | 19 - .../shippers/elastic_v3/server/jest.config.js | 13 - .../shippers/elastic_v3/server/kibana.jsonc | 5 - .../shippers/elastic_v3/server/package.json | 7 - .../server/src/server_shipper.test.ts | 624 -------------- .../shippers/elastic_v3/server/tsconfig.json | 21 - .../shippers/fullstory/jest.config.js | 13 - .../analytics/shippers/fullstory/kibana.jsonc | 5 - .../analytics/shippers/fullstory/package.json | 7 - .../shippers/fullstory/tsconfig.json | 21 - .../src/analytics_service.test.mocks.ts | 4 +- .../src/analytics_service.ts | 4 +- .../src/track_clicks.ts | 2 +- .../src/track_performance_measure_entries.ts | 2 +- .../src/track_viewport_size.ts | 2 +- .../tsconfig.json | 2 +- .../analytics/core-analytics-browser/index.ts | 38 + .../core-analytics-browser/src/types.ts | 2 +- .../core-analytics-browser/tsconfig.json | 2 +- .../src/analytics_service.test.mocks.ts | 4 +- .../src/analytics_service.ts | 4 +- .../tsconfig.json | 2 +- .../analytics/core-analytics-server/index.ts | 38 + .../core-analytics-server/src/contracts.ts | 2 +- .../core-analytics-server/tsconfig.json | 2 +- .../src/toasts/telemetry/event_types.ts | 2 +- .../tsconfig.json | 2 +- .../src/status_service.ts | 2 +- .../core-status-server-internal/tsconfig.json | 2 +- .../performance_metric_events/helpers.test.ts | 2 +- .../src/performance_metric_events/helpers.ts | 2 +- .../src/performance_metric_events/schema.ts | 2 +- packages/kbn-ebt-tools/tsconfig.json | 5 +- src/core/public/index.ts | 40 +- src/core/server/index.ts | 42 +- src/core/tsconfig.json | 1 - .../register_ebt_counters.test.ts | 2 +- .../register_ebt_counters.test.ts | 2 +- .../kibana_usage_collection/tsconfig.json | 1 - src/plugins/telemetry/public/plugin.test.ts | 2 +- src/plugins/telemetry/public/plugin.ts | 2 +- src/plugins/telemetry/server/plugin.test.ts | 2 +- src/plugins/telemetry/server/plugin.ts | 2 +- src/plugins/telemetry/tsconfig.json | 3 +- .../server/collector/types.ts | 4 +- src/plugins/usage_collection/tsconfig.json | 2 +- .../common/fetch_events.ts | 2 +- .../analytics_ftr_helpers/common/types.ts | 2 +- .../public/custom_shipper.ts | 3 +- .../server/custom_shipper.ts | 3 +- .../analytics_ftr_helpers/tsconfig.json | 2 +- .../core_overall_status_changed.ts | 2 +- test/tsconfig.json | 1 - tsconfig.base.json | 12 +- ...r_cloud_deployment_id_analytics_context.ts | 2 +- x-pack/plugins/cloud/tsconfig.json | 2 +- .../cloud_full_story/public/plugin.ts | 2 +- .../cloud_full_story/tsconfig.json | 2 +- .../lib/telemetry/event_based_telemetry.ts | 2 +- .../plugins/elastic_assistant/tsconfig.json | 1 - .../services/telemetry/fleet_usages_schema.ts | 2 +- x-pack/plugins/fleet/tsconfig.json | 1 - .../public/telemetry/event_types.ts | 3 +- .../plugins/global_search_bar/tsconfig.json | 1 - .../register_analytics_context_provider.ts | 2 +- x-pack/plugins/licensing/tsconfig.json | 4 +- .../apm/public/services/telemetry/types.ts | 3 +- .../observability_solution/apm/tsconfig.json | 1 - .../infra/public/services/telemetry/types.ts | 3 +- .../infra/tsconfig.json | 1 - .../public/analytics/schemas/chat_feedback.ts | 2 +- .../public/analytics/schemas/common.ts | 2 +- .../analytics/schemas/insight_feedback.ts | 2 +- .../analytics/schemas/user_sent_prompt.ts | 2 +- .../server/analytics/recall_ranking.ts | 2 +- .../observability_ai_assistant/tsconfig.json | 1 - .../common/telemetry_events.ts | 2 +- .../observability_logs_explorer/tsconfig.json | 2 +- .../common/telemetry_events.ts | 2 +- .../observability_onboarding/tsconfig.json | 4 +- .../server/usage/register_event_types.ts | 4 +- x-pack/plugins/reporting/tsconfig.json | 1 - .../server/analytics/events.ts | 2 +- .../plugins/search_playground/tsconfig.json | 1 - .../server/analytics/analytics_service.ts | 7 +- x-pack/plugins/security/tsconfig.json | 1 - .../telemetry/events/ai_assistant/types.ts | 2 +- .../telemetry/events/alerts_grouping/types.ts | 2 +- .../events/attack_discovery/types.ts | 2 +- .../telemetry/events/data_quality/types.ts | 2 +- .../events/document_details/types.ts | 2 +- .../events/entity_analytics/types.ts | 2 +- .../lib/telemetry/events/onboarding/types.ts | 2 +- .../public/common/lib/telemetry/types.ts | 3 +- .../query_tab_unified_components.test.tsx | 2 +- .../unified_components/index.test.tsx | 4 +- .../lib/telemetry/event_based/events.ts | 2 +- .../plugins/security_solution/tsconfig.json | 1 - .../server/telemetry/event_based_telemetry.ts | 2 +- .../tsconfig.json | 1 - yarn.lock | 24 +- 181 files changed, 1446 insertions(+), 1612 deletions(-) delete mode 100644 packages/analytics/README.md create mode 100644 packages/analytics/ebt/README.md rename packages/analytics/{ => ebt}/client/README.md (99%) rename packages/analytics/{ => ebt}/client/index.ts (98%) rename packages/analytics/{ => ebt}/client/src/analytics_client/analytics_client.test.ts (65%) rename packages/analytics/{ => ebt}/client/src/analytics_client/analytics_client.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/context_service.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/context_service.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/index.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/mocks.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/opt_in_config.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/opt_in_config.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/shippers_registry.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/shippers_registry.ts (100%) rename packages/analytics/{ => ebt}/client/src/analytics_client/types.ts (100%) rename packages/analytics/{ => ebt}/client/src/events/index.ts (100%) rename packages/analytics/{ => ebt}/client/src/events/types.ts (100%) rename packages/analytics/{ => ebt}/client/src/mocks.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/index.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/types.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/types.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/excess.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/excess.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/index.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/schema_to_io_ts.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/schema_to_io_ts.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/validate_schema.test.ts (100%) rename packages/analytics/{ => ebt}/client/src/schema/validation/validate_schema.ts (100%) rename packages/analytics/{ => ebt}/client/src/shippers/index.ts (100%) rename packages/analytics/{ => ebt}/client/src/shippers/mocks.ts (100%) rename packages/analytics/{ => ebt}/client/src/shippers/types.ts (100%) create mode 100644 packages/analytics/ebt/index.ts rename packages/analytics/{client => ebt}/jest.config.js (77%) rename packages/analytics/{client => ebt}/kibana.jsonc (66%) rename packages/analytics/{client => ebt}/package.json (59%) rename packages/analytics/{ => ebt}/shippers/README.md (91%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/browser/README.md (79%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/browser/index.ts (82%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/browser/src/browser_shipper.test.ts (51%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/browser/src/browser_shipper.ts (95%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/README.md (73%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/index.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/build_headers.test.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/build_headers.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/build_url.test.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/build_url.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/error_with_code.test.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/error_with_code.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/events_to_ndjson.test.ts (96%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/events_to_ndjson.ts (92%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts (98%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/report_telemetry_counters.ts (98%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/common/src/types.ts (100%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/server/README.md (83%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/server/index.ts (82%) rename packages/analytics/{ => ebt}/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts (100%) create mode 100644 packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.test.ts rename packages/analytics/{ => ebt}/shippers/elastic_v3/server/src/server_shipper.ts (99%) rename packages/analytics/{ => ebt}/shippers/fullstory/README.md (91%) rename packages/analytics/{ => ebt}/shippers/fullstory/index.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/format_payload.test.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/format_payload.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/fullstory_shipper.test.mocks.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/fullstory_shipper.test.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/fullstory_shipper.ts (96%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/get_parsed_version.test.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/get_parsed_version.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/load_snippet.test.ts (68%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/load_snippet.ts (100%) rename packages/analytics/{ => ebt}/shippers/fullstory/src/types.ts (100%) rename packages/analytics/{client => ebt}/tsconfig.json (63%) delete mode 100644 packages/analytics/shippers/elastic_v3/browser/jest.config.js delete mode 100644 packages/analytics/shippers/elastic_v3/browser/kibana.jsonc delete mode 100644 packages/analytics/shippers/elastic_v3/browser/package.json delete mode 100644 packages/analytics/shippers/elastic_v3/browser/tsconfig.json delete mode 100644 packages/analytics/shippers/elastic_v3/common/jest.config.js delete mode 100644 packages/analytics/shippers/elastic_v3/common/kibana.jsonc delete mode 100644 packages/analytics/shippers/elastic_v3/common/package.json delete mode 100644 packages/analytics/shippers/elastic_v3/common/tsconfig.json delete mode 100644 packages/analytics/shippers/elastic_v3/server/jest.config.js delete mode 100644 packages/analytics/shippers/elastic_v3/server/kibana.jsonc delete mode 100644 packages/analytics/shippers/elastic_v3/server/package.json delete mode 100644 packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts delete mode 100644 packages/analytics/shippers/elastic_v3/server/tsconfig.json delete mode 100644 packages/analytics/shippers/fullstory/jest.config.js delete mode 100644 packages/analytics/shippers/fullstory/kibana.jsonc delete mode 100644 packages/analytics/shippers/fullstory/package.json delete mode 100644 packages/analytics/shippers/fullstory/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 44c2a4f27636b..a5fc58216acbf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -35,14 +35,9 @@ packages/kbn-ambient-ftr-types @elastic/kibana-operations @elastic/appex-qa packages/kbn-ambient-storybook-types @elastic/kibana-operations packages/kbn-ambient-ui-types @elastic/kibana-operations packages/kbn-analytics @elastic/kibana-core -packages/analytics/client @elastic/kibana-core packages/analytics/utils/analytics_collection_utils @elastic/kibana-core test/analytics/plugins/analytics_ftr_helpers @elastic/kibana-core test/analytics/plugins/analytics_plugin_a @elastic/kibana-core -packages/analytics/shippers/elastic_v3/browser @elastic/kibana-core -packages/analytics/shippers/elastic_v3/common @elastic/kibana-core -packages/analytics/shippers/elastic_v3/server @elastic/kibana-core -packages/analytics/shippers/fullstory @elastic/kibana-core packages/kbn-apm-config-loader @elastic/kibana-core @vigneshshanmugam x-pack/plugins/observability_solution/apm_data_access @elastic/obs-knowledge-team @elastic/obs-ux-infra_services-team packages/kbn-apm-data-view @elastic/obs-ux-infra_services-team @@ -378,6 +373,7 @@ packages/kbn-discover-utils @elastic/kibana-data-discovery packages/kbn-doc-links @elastic/docs packages/kbn-docs-utils @elastic/kibana-operations packages/kbn-dom-drag-drop @elastic/kibana-visualizations @elastic/kibana-data-discovery +packages/analytics/ebt @elastic/kibana-core packages/kbn-ebt-tools @elastic/kibana-core x-pack/packages/security-solution/ecs_data_quality_dashboard @elastic/security-threat-hunting-explore x-pack/plugins/ecs_data_quality_dashboard @elastic/security-threat-hunting-explore diff --git a/package.json b/package.json index eaae0b675e62e..d893459351783 100644 --- a/package.json +++ b/package.json @@ -166,14 +166,9 @@ "@kbn/alerts-restricted-fixtures-plugin": "link:x-pack/test/alerting_api_integration/common/plugins/alerts_restricted", "@kbn/alerts-ui-shared": "link:packages/kbn-alerts-ui-shared", "@kbn/analytics": "link:packages/kbn-analytics", - "@kbn/analytics-client": "link:packages/analytics/client", "@kbn/analytics-collection-utils": "link:packages/analytics/utils/analytics_collection_utils", "@kbn/analytics-ftr-helpers-plugin": "link:test/analytics/plugins/analytics_ftr_helpers", "@kbn/analytics-plugin-a-plugin": "link:test/analytics/plugins/analytics_plugin_a", - "@kbn/analytics-shippers-elastic-v3-browser": "link:packages/analytics/shippers/elastic_v3/browser", - "@kbn/analytics-shippers-elastic-v3-common": "link:packages/analytics/shippers/elastic_v3/common", - "@kbn/analytics-shippers-elastic-v3-server": "link:packages/analytics/shippers/elastic_v3/server", - "@kbn/analytics-shippers-fullstory": "link:packages/analytics/shippers/fullstory", "@kbn/apm-config-loader": "link:packages/kbn-apm-config-loader", "@kbn/apm-data-access-plugin": "link:x-pack/plugins/observability_solution/apm_data_access", "@kbn/apm-data-view": "link:packages/kbn-apm-data-view", @@ -433,6 +428,7 @@ "@kbn/discover-utils": "link:packages/kbn-discover-utils", "@kbn/doc-links": "link:packages/kbn-doc-links", "@kbn/dom-drag-drop": "link:packages/kbn-dom-drag-drop", + "@kbn/ebt": "link:packages/analytics/ebt", "@kbn/ebt-tools": "link:packages/kbn-ebt-tools", "@kbn/ecs-data-quality-dashboard": "link:x-pack/packages/security-solution/ecs_data_quality_dashboard", "@kbn/ecs-data-quality-dashboard-plugin": "link:x-pack/plugins/ecs_data_quality_dashboard", diff --git a/packages/analytics/README.md b/packages/analytics/README.md deleted file mode 100644 index a9198dae88975..0000000000000 --- a/packages/analytics/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# @kbn/analytics-* - -This module implements the Analytics client used for Event-Based Telemetry. The intention of the client is to be usable on both: the UI and the Server sides. - -## Client - -Holds the public APIs to report events, enrich the events' context and set up the transport mechanisms. Refer to the [client's docs](./client/README.md) for more information. - -## Prebuilt shippers - -Elastic-approved shippers are available as `@kbn/analytics-shippers-*` packages. Refer to the [shippers' docs](./shippers/README.md) for more information. diff --git a/packages/analytics/ebt/README.md b/packages/analytics/ebt/README.md new file mode 100644 index 0000000000000..8758a90304cba --- /dev/null +++ b/packages/analytics/ebt/README.md @@ -0,0 +1,11 @@ +# @kbn/ebt/* + +This module implements the Analytics client used for Event-Based Telemetry. The intention of the client is to be usable on both: the UI and the Server sides. + +## Client + +`@kbn/ebt/client` holds the public APIs to report events, enrich the events' context and set up the transport mechanisms. Refer to the [client's docs](./client/README.md) for more information. + +## Prebuilt shippers + +Elastic-approved shippers are available as `@kbn/ebt/shippers/*` packages. Refer to the [shippers' docs](./shippers/README.md) for more information. diff --git a/packages/analytics/client/README.md b/packages/analytics/ebt/client/README.md similarity index 99% rename from packages/analytics/client/README.md rename to packages/analytics/ebt/client/README.md index e51795faa6a03..508fc984c1a58 100644 --- a/packages/analytics/client/README.md +++ b/packages/analytics/ebt/client/README.md @@ -1,4 +1,4 @@ -# @kbn/analytics-client +# @kbn/ebt/client This module implements the Analytics client used for Event-Based Telemetry. The intention of the client is to be usable on both: the UI and the Server sides. @@ -7,7 +7,7 @@ This module implements the Analytics client used for Event-Based Telemetry. The It all starts by creating the client with the `createAnalytics` API: ```typescript -import { createAnalytics } from '@kbn/analytics-client'; +import { createAnalytics } from '@kbn/ebt/client'; const analytics = createAnalytics({ // Set to `true` when running in developer mode. @@ -167,7 +167,7 @@ import type { EventContext, IShipper, TelemetryCounter -} from '@kbn/analytics-client'; +} from '@kbn/ebt/client'; class MyVeryOwnShipper implements IShipper { constructor(myOptions: MyOptions, initContext: AnalyticsClientInitContext) { diff --git a/packages/analytics/client/index.ts b/packages/analytics/ebt/client/index.ts similarity index 98% rename from packages/analytics/client/index.ts rename to packages/analytics/ebt/client/index.ts index 4354d1f2d0cfd..7127a21a5517e 100644 --- a/packages/analytics/client/index.ts +++ b/packages/analytics/ebt/client/index.ts @@ -33,6 +33,7 @@ export type { ShipperName, // Types for the registerContextProvider API ContextProviderOpts, + ContextProviderName, // Types for the registerEventType API EventTypeOpts, } from './src/analytics_client'; diff --git a/packages/analytics/client/src/analytics_client/analytics_client.test.ts b/packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts similarity index 65% rename from packages/analytics/client/src/analytics_client/analytics_client.test.ts rename to packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts index 650b1e1b4e750..0d72f003e77a6 100644 --- a/packages/analytics/client/src/analytics_client/analytics_client.test.ts +++ b/packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts @@ -8,7 +8,6 @@ // eslint-disable-next-line max-classes-per-file import { Subject, lastValueFrom, take, toArray } from 'rxjs'; -import { fakeSchedulers } from 'rxjs-marbles/jest'; import type { MockedLogger } from '@kbn/logging-mocks'; import { loggerMock } from '@kbn/logging-mocks'; import { AnalyticsClient } from './analytics_client'; @@ -21,7 +20,7 @@ describe('AnalyticsClient', () => { let logger: MockedLogger; beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); + jest.useFakeTimers(); logger = loggerMock.create(); analyticsClient = new AnalyticsClient({ logger, @@ -338,76 +337,67 @@ describe('AnalyticsClient', () => { expect(optIn).toHaveBeenCalledWith(true); }); - test( - 'Spreads the context updates to the shipper (only after opt-in)', - fakeSchedulers((advance) => { - const extendContextMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper, { extendContextMock }); - expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in - analyticsClient.optIn({ global: { enabled: true } }); - advance(10); - expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context - - const context$ = new Subject<{ a_field: boolean }>(); - analyticsClient.registerContextProvider({ - name: 'contextProviderA', - schema: { - a_field: { - type: 'boolean', - _meta: { - description: 'a_field description', - }, + test('Spreads the context updates to the shipper (only after opt-in)', async () => { + const extendContextMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper, { extendContextMock }); + expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in + analyticsClient.optIn({ global: { enabled: true } }); + await jest.advanceTimersByTimeAsync(10); + expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context + + const context$ = new Subject<{ a_field: boolean }>(); + analyticsClient.registerContextProvider({ + name: 'contextProviderA', + schema: { + a_field: { + type: 'boolean', + _meta: { + description: 'a_field description', }, }, - context$, - }); + }, + context$, + }); - context$.next({ a_field: true }); - expect(extendContextMock).toHaveBeenCalledWith({ a_field: true }); // After update - }) - ); - - test( - 'Does not spread the context if opt-in === false', - fakeSchedulers((advance) => { - const extendContextMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper, { extendContextMock }); - expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in - analyticsClient.optIn({ global: { enabled: false } }); - advance(10); - expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in - }) - ); - - test( - 'Handles errors in the shipper', - fakeSchedulers(async (advance) => { - const optInMock = jest.fn().mockImplementation(() => { - throw new Error('Something went terribly wrong'); - }); - const extendContextMock = jest.fn().mockImplementation(() => { - throw new Error('Something went terribly wrong'); - }); - const shutdownMock = jest.fn().mockImplementation(() => { - throw new Error('Something went terribly wrong'); - }); - analyticsClient.registerShipper(MockedShipper, { - optInMock, - extendContextMock, - shutdownMock, - }); - expect(() => analyticsClient.optIn({ global: { enabled: true } })).not.toThrow(); - advance(10); - expect(optInMock).toHaveBeenCalledWith(true); - expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context - expect(logger.warn).toHaveBeenCalledWith( - `Shipper "${MockedShipper.shipperName}" failed to extend the context`, - expect.any(Error) - ); - await expect(analyticsClient.shutdown()).resolves.toBeUndefined(); - expect(shutdownMock).toHaveBeenCalled(); - }) - ); + context$.next({ a_field: true }); + expect(extendContextMock).toHaveBeenCalledWith({ a_field: true }); // After update + }); + + test('Does not spread the context if opt-in === false', async () => { + const extendContextMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper, { extendContextMock }); + expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in + analyticsClient.optIn({ global: { enabled: false } }); + await jest.advanceTimersByTimeAsync(10); + expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in + }); + + test('Handles errors in the shipper', async () => { + const optInMock = jest.fn().mockImplementation(() => { + throw new Error('Something went terribly wrong'); + }); + const extendContextMock = jest.fn().mockImplementation(() => { + throw new Error('Something went terribly wrong'); + }); + const shutdownMock = jest.fn().mockImplementation(() => { + throw new Error('Something went terribly wrong'); + }); + analyticsClient.registerShipper(MockedShipper, { + optInMock, + extendContextMock, + shutdownMock, + }); + expect(() => analyticsClient.optIn({ global: { enabled: true } })).not.toThrow(); + await jest.advanceTimersByTimeAsync(10); + expect(optInMock).toHaveBeenCalledWith(true); + expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context + expect(logger.warn).toHaveBeenCalledWith( + `Shipper "${MockedShipper.shipperName}" failed to extend the context`, + expect.any(Error) + ); + await expect(analyticsClient.shutdown()).resolves.toBeUndefined(); + expect(shutdownMock).toHaveBeenCalled(); + }); }); describe('ContextProvider APIs', () => { @@ -633,89 +623,86 @@ describe('AnalyticsClient', () => { ]); }); - test( - 'Sends events from the internal queue when there are shippers and an opt-in response is true', - fakeSchedulers(async (advance) => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - // As proven in the previous test, the events are still enqueued. - // Let's register a shipper and opt-in to test the dequeue logic. - const reportEventsMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); - analyticsClient.optIn({ global: { enabled: true } }); - advance(10); - - expect(reportEventsMock).toHaveBeenCalledTimes(2); - expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'a' }, - timestamp: expect.any(String), - }, - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'b' }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock).toHaveBeenNthCalledWith(2, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - - // Expect 3 enqueued events, and 2 sent_to_shipper batched requests - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-a', - code: 'OK', - count: 2, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }) - ); + test('Sends events from the internal queue when there are shippers and an opt-in response is true', async () => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + // As proven in the previous test, the events are still enqueued. + // Let's register a shipper and opt-in to test the dequeue logic. + const reportEventsMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); + analyticsClient.optIn({ global: { enabled: true } }); + await jest.advanceTimersByTimeAsync(10); + + expect(reportEventsMock).toHaveBeenCalledTimes(2); + expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'a' }, + timestamp: expect.any(String), + }, + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'b' }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock).toHaveBeenNthCalledWith(2, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + + // Expect 3 enqueued events, and 2 sent_to_shipper batched requests + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-a', + code: 'OK', + count: 2, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }); test('Discards events from the internal queue when there are shippers and an opt-in response is false', async () => { const telemetryCounterPromise = lastValueFrom( @@ -823,259 +810,250 @@ describe('AnalyticsClient', () => { expect(analyticsClient['internalEventQueue$'].observed).toBe(false); }); - test( - 'Discards only one type of the enqueued events based on event_type config', - fakeSchedulers(async (advance) => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 1), toArray()) // Waiting for 3 enqueued + 1 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - const reportEventsMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); - analyticsClient.optIn({ - global: { enabled: true }, - event_types: { ['event-type-a']: { enabled: false } }, - }); - advance(10); - - expect(reportEventsMock).toHaveBeenCalledTimes(1); - expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - - // Expect 3 enqueued events, and 1 sent_to_shipper batched request - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }) - ); - - test( - 'Discards the event at the shipper level (for a specific event)', - fakeSchedulers(async (advance) => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - // Register 2 shippers and set 1 of them as disabled for event-type-a - const reportEventsMock1 = jest.fn(); - const reportEventsMock2 = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); - analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); - analyticsClient.optIn({ - global: { enabled: true }, - event_types: { - ['event-type-a']: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, - }, - }); - advance(10); - - expect(reportEventsMock1).toHaveBeenCalledTimes(2); - expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'a' }, - timestamp: expect.any(String), - }, - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'b' }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock2).toHaveBeenCalledTimes(1); - expect(reportEventsMock2).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - - // Expect 3 enqueued events, and 2 sent_to_shipper batched requests - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-a', - code: 'OK', - count: 2, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }) - ); - - test( - 'Discards all the events at the shipper level (globally disabled)', - fakeSchedulers(async (advance) => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - // Register 2 shippers and set 1 of them as globally disabled - const reportEventsMock1 = jest.fn(); - const reportEventsMock2 = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); - analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); - analyticsClient.optIn({ - global: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, - event_types: { - ['event-type-a']: { enabled: true }, - }, - }); - advance(10); - - expect(reportEventsMock1).toHaveBeenCalledTimes(2); - expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'a' }, - timestamp: expect.any(String), - }, - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'b' }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock2).toHaveBeenCalledTimes(0); - - // Expect 3 enqueued events, and 2 sent_to_shipper batched requests - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-a', - code: 'OK', - count: 2, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }) - ); + test('Discards only one type of the enqueued events based on event_type config', async () => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 1), toArray()) // Waiting for 3 enqueued + 1 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + const reportEventsMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); + analyticsClient.optIn({ + global: { enabled: true }, + event_types: { ['event-type-a']: { enabled: false } }, + }); + await jest.advanceTimersByTimeAsync(10); + + expect(reportEventsMock).toHaveBeenCalledTimes(1); + expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + + // Expect 3 enqueued events, and 1 sent_to_shipper batched request + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }); + + test('Discards the event at the shipper level (for a specific event)', async () => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + // Register 2 shippers and set 1 of them as disabled for event-type-a + const reportEventsMock1 = jest.fn(); + const reportEventsMock2 = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); + analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); + analyticsClient.optIn({ + global: { enabled: true }, + event_types: { + ['event-type-a']: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, + }, + }); + await jest.advanceTimersByTimeAsync(10); + + expect(reportEventsMock1).toHaveBeenCalledTimes(2); + expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'a' }, + timestamp: expect.any(String), + }, + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'b' }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock2).toHaveBeenCalledTimes(1); + expect(reportEventsMock2).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + + // Expect 3 enqueued events, and 2 sent_to_shipper batched requests + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-a', + code: 'OK', + count: 2, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }); + + test('Discards all the events at the shipper level (globally disabled)', async () => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + // Register 2 shippers and set 1 of them as globally disabled + const reportEventsMock1 = jest.fn(); + const reportEventsMock2 = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); + analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); + analyticsClient.optIn({ + global: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, + event_types: { + ['event-type-a']: { enabled: true }, + }, + }); + await jest.advanceTimersByTimeAsync(10); + + expect(reportEventsMock1).toHaveBeenCalledTimes(2); + expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'a' }, + timestamp: expect.any(String), + }, + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'b' }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock2).toHaveBeenCalledTimes(0); + + // Expect 3 enqueued events, and 2 sent_to_shipper batched requests + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-a', + code: 'OK', + count: 2, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }); test('Discards incoming events when opt-in response is false', async () => { // Set OptIn and shipper first to test the "once-set up" scenario diff --git a/packages/analytics/client/src/analytics_client/analytics_client.ts b/packages/analytics/ebt/client/src/analytics_client/analytics_client.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/analytics_client.ts rename to packages/analytics/ebt/client/src/analytics_client/analytics_client.ts diff --git a/packages/analytics/client/src/analytics_client/context_service.test.ts b/packages/analytics/ebt/client/src/analytics_client/context_service.test.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/context_service.test.ts rename to packages/analytics/ebt/client/src/analytics_client/context_service.test.ts diff --git a/packages/analytics/client/src/analytics_client/context_service.ts b/packages/analytics/ebt/client/src/analytics_client/context_service.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/context_service.ts rename to packages/analytics/ebt/client/src/analytics_client/context_service.ts diff --git a/packages/analytics/client/src/analytics_client/index.ts b/packages/analytics/ebt/client/src/analytics_client/index.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/index.ts rename to packages/analytics/ebt/client/src/analytics_client/index.ts diff --git a/packages/analytics/client/src/analytics_client/mocks.ts b/packages/analytics/ebt/client/src/analytics_client/mocks.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/mocks.ts rename to packages/analytics/ebt/client/src/analytics_client/mocks.ts diff --git a/packages/analytics/client/src/analytics_client/opt_in_config.test.ts b/packages/analytics/ebt/client/src/analytics_client/opt_in_config.test.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/opt_in_config.test.ts rename to packages/analytics/ebt/client/src/analytics_client/opt_in_config.test.ts diff --git a/packages/analytics/client/src/analytics_client/opt_in_config.ts b/packages/analytics/ebt/client/src/analytics_client/opt_in_config.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/opt_in_config.ts rename to packages/analytics/ebt/client/src/analytics_client/opt_in_config.ts diff --git a/packages/analytics/client/src/analytics_client/shippers_registry.test.ts b/packages/analytics/ebt/client/src/analytics_client/shippers_registry.test.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/shippers_registry.test.ts rename to packages/analytics/ebt/client/src/analytics_client/shippers_registry.test.ts diff --git a/packages/analytics/client/src/analytics_client/shippers_registry.ts b/packages/analytics/ebt/client/src/analytics_client/shippers_registry.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/shippers_registry.ts rename to packages/analytics/ebt/client/src/analytics_client/shippers_registry.ts diff --git a/packages/analytics/client/src/analytics_client/types.ts b/packages/analytics/ebt/client/src/analytics_client/types.ts similarity index 100% rename from packages/analytics/client/src/analytics_client/types.ts rename to packages/analytics/ebt/client/src/analytics_client/types.ts diff --git a/packages/analytics/client/src/events/index.ts b/packages/analytics/ebt/client/src/events/index.ts similarity index 100% rename from packages/analytics/client/src/events/index.ts rename to packages/analytics/ebt/client/src/events/index.ts diff --git a/packages/analytics/client/src/events/types.ts b/packages/analytics/ebt/client/src/events/types.ts similarity index 100% rename from packages/analytics/client/src/events/types.ts rename to packages/analytics/ebt/client/src/events/types.ts diff --git a/packages/analytics/client/src/mocks.ts b/packages/analytics/ebt/client/src/mocks.ts similarity index 100% rename from packages/analytics/client/src/mocks.ts rename to packages/analytics/ebt/client/src/mocks.ts diff --git a/packages/analytics/client/src/schema/index.ts b/packages/analytics/ebt/client/src/schema/index.ts similarity index 100% rename from packages/analytics/client/src/schema/index.ts rename to packages/analytics/ebt/client/src/schema/index.ts diff --git a/packages/analytics/client/src/schema/types.test.ts b/packages/analytics/ebt/client/src/schema/types.test.ts similarity index 100% rename from packages/analytics/client/src/schema/types.test.ts rename to packages/analytics/ebt/client/src/schema/types.test.ts diff --git a/packages/analytics/client/src/schema/types.ts b/packages/analytics/ebt/client/src/schema/types.ts similarity index 100% rename from packages/analytics/client/src/schema/types.ts rename to packages/analytics/ebt/client/src/schema/types.ts diff --git a/packages/analytics/client/src/schema/validation/excess.test.ts b/packages/analytics/ebt/client/src/schema/validation/excess.test.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/excess.test.ts rename to packages/analytics/ebt/client/src/schema/validation/excess.test.ts diff --git a/packages/analytics/client/src/schema/validation/excess.ts b/packages/analytics/ebt/client/src/schema/validation/excess.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/excess.ts rename to packages/analytics/ebt/client/src/schema/validation/excess.ts diff --git a/packages/analytics/client/src/schema/validation/index.ts b/packages/analytics/ebt/client/src/schema/validation/index.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/index.ts rename to packages/analytics/ebt/client/src/schema/validation/index.ts diff --git a/packages/analytics/client/src/schema/validation/schema_to_io_ts.test.ts b/packages/analytics/ebt/client/src/schema/validation/schema_to_io_ts.test.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/schema_to_io_ts.test.ts rename to packages/analytics/ebt/client/src/schema/validation/schema_to_io_ts.test.ts diff --git a/packages/analytics/client/src/schema/validation/schema_to_io_ts.ts b/packages/analytics/ebt/client/src/schema/validation/schema_to_io_ts.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/schema_to_io_ts.ts rename to packages/analytics/ebt/client/src/schema/validation/schema_to_io_ts.ts diff --git a/packages/analytics/client/src/schema/validation/validate_schema.test.ts b/packages/analytics/ebt/client/src/schema/validation/validate_schema.test.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/validate_schema.test.ts rename to packages/analytics/ebt/client/src/schema/validation/validate_schema.test.ts diff --git a/packages/analytics/client/src/schema/validation/validate_schema.ts b/packages/analytics/ebt/client/src/schema/validation/validate_schema.ts similarity index 100% rename from packages/analytics/client/src/schema/validation/validate_schema.ts rename to packages/analytics/ebt/client/src/schema/validation/validate_schema.ts diff --git a/packages/analytics/client/src/shippers/index.ts b/packages/analytics/ebt/client/src/shippers/index.ts similarity index 100% rename from packages/analytics/client/src/shippers/index.ts rename to packages/analytics/ebt/client/src/shippers/index.ts diff --git a/packages/analytics/client/src/shippers/mocks.ts b/packages/analytics/ebt/client/src/shippers/mocks.ts similarity index 100% rename from packages/analytics/client/src/shippers/mocks.ts rename to packages/analytics/ebt/client/src/shippers/mocks.ts diff --git a/packages/analytics/client/src/shippers/types.ts b/packages/analytics/ebt/client/src/shippers/types.ts similarity index 100% rename from packages/analytics/client/src/shippers/types.ts rename to packages/analytics/ebt/client/src/shippers/types.ts diff --git a/packages/analytics/ebt/index.ts b/packages/analytics/ebt/index.ts new file mode 100644 index 0000000000000..ec407b406d406 --- /dev/null +++ b/packages/analytics/ebt/index.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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. + */ + +// Exporting the types here as a utility only +// The recommended way of using this library is to import from the subdirectories /client, /shippers/* +// The reason is to avoid leaking server-side code to the browser, and vice-versa +export type { + AnalyticsClient, + // Types for the constructor + AnalyticsClientInitContext, + // Types for the registerShipper API + ShipperClassConstructor, + RegisterShipperOpts, + // Types for the optIn API + OptInConfig, + OptInConfigPerType, + ShipperName, + // Types for the registerContextProvider API + ContextProviderOpts, + ContextProviderName, + // Types for the registerEventType API + EventTypeOpts, + // Events + Event, + EventContext, + EventType, + TelemetryCounter, + TelemetryCounterType, + // Schema + RootSchema, + SchemaObject, + SchemaArray, + SchemaChildValue, + SchemaMeta, + SchemaValue, + SchemaMetaOptional, + PossibleSchemaTypes, + AllowedSchemaBooleanTypes, + AllowedSchemaNumberTypes, + AllowedSchemaStringTypes, + AllowedSchemaTypes, + // Shippers + IShipper, +} from './client'; +export type { ElasticV3ShipperOptions } from './shippers/elastic_v3/common'; +export type { ElasticV3BrowserShipper } from './shippers/elastic_v3/browser'; +export type { ElasticV3ServerShipper } from './shippers/elastic_v3/server'; +export type { + FullStoryShipperConfig, + FullStoryShipper, + FullStorySnippetConfig, +} from './shippers/fullstory'; diff --git a/packages/analytics/client/jest.config.js b/packages/analytics/ebt/jest.config.js similarity index 77% rename from packages/analytics/client/jest.config.js rename to packages/analytics/ebt/jest.config.js index aa0d319f9d1e7..7296624c287b5 100644 --- a/packages/analytics/client/jest.config.js +++ b/packages/analytics/ebt/jest.config.js @@ -7,7 +7,7 @@ */ module.exports = { - preset: '@kbn/test/jest_node', - rootDir: '../../../', - roots: ['/packages/analytics/client'], + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/packages/analytics/ebt'], }; diff --git a/packages/analytics/client/kibana.jsonc b/packages/analytics/ebt/kibana.jsonc similarity index 66% rename from packages/analytics/client/kibana.jsonc rename to packages/analytics/ebt/kibana.jsonc index a027e7ee866b5..947d6224b6933 100644 --- a/packages/analytics/client/kibana.jsonc +++ b/packages/analytics/ebt/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", - "id": "@kbn/analytics-client", + "id": "@kbn/ebt", "owner": "@elastic/kibana-core" } diff --git a/packages/analytics/client/package.json b/packages/analytics/ebt/package.json similarity index 59% rename from packages/analytics/client/package.json rename to packages/analytics/ebt/package.json index 6db911a1bac86..aee987a4c179b 100644 --- a/packages/analytics/client/package.json +++ b/packages/analytics/ebt/package.json @@ -1,7 +1,6 @@ { - "name": "@kbn/analytics-client", + "name": "@kbn/ebt", "private": true, "version": "1.0.0", - "author": "Kibana Core", "license": "SSPL-1.0 OR Elastic License 2.0" } \ No newline at end of file diff --git a/packages/analytics/shippers/README.md b/packages/analytics/ebt/shippers/README.md similarity index 91% rename from packages/analytics/shippers/README.md rename to packages/analytics/ebt/shippers/README.md index 5ab85d08ff2ca..3f312d1ecefe3 100644 --- a/packages/analytics/shippers/README.md +++ b/packages/analytics/ebt/shippers/README.md @@ -1,4 +1,4 @@ -# @kbn/analytics-shippers-* +# @kbn/ebt/shippers/* This directory holds the implementation of the _built-in_ shippers provided by the Analytics client. At the moment, the shippers are: diff --git a/packages/analytics/shippers/elastic_v3/browser/README.md b/packages/analytics/ebt/shippers/elastic_v3/browser/README.md similarity index 79% rename from packages/analytics/shippers/elastic_v3/browser/README.md rename to packages/analytics/ebt/shippers/elastic_v3/browser/README.md index fcdd5e8a3ca2e..1253a9619233d 100644 --- a/packages/analytics/shippers/elastic_v3/browser/README.md +++ b/packages/analytics/ebt/shippers/elastic_v3/browser/README.md @@ -1,13 +1,13 @@ -# @kbn/analytics-shippers-elastic-v3-browser +# @kbn/ebt/shippers/elastic_v3/browser -UI-side implementation of the Elastic V3 shipper for the `@kbn/analytics-client`. +UI-side implementation of the Elastic V3 shipper for the `@kbn/ebt/client`. ## How to use it -This module is intended to be used **on the browser only**. Due to the nature of the UI events, they are usually more scattered in time, and we can assume a much lower load than the server. For that reason, it doesn't apply the necessary backpressure mechanisms to prevent the server from getting overloaded with too many events neither identifies if the server sits behind a firewall to discard any incoming events. Refer to `@kbn/analytics-shippers-elastic-v3-server` for the server-side implementation. +This module is intended to be used **on the browser only**. Due to the nature of the UI events, they are usually more scattered in time, and we can assume a much lower load than the server. For that reason, it doesn't apply the necessary backpressure mechanisms to prevent the server from getting overloaded with too many events neither identifies if the server sits behind a firewall to discard any incoming events. Refer to `@kbn/ebt/shippers/elastic_v3/server` for the server-side implementation. ```typescript -import { ElasticV3BrowserShipper } from "@kbn/analytics-shippers-elastic-v3-browser"; +import { ElasticV3BrowserShipper } from "@kbn/ebt/shippers/elastic_v3/browser"; analytics.registerShipper(ElasticV3BrowserShipper, { channelName: 'myChannel', version: '1.0.0' }); ``` diff --git a/packages/analytics/shippers/elastic_v3/browser/index.ts b/packages/analytics/ebt/shippers/elastic_v3/browser/index.ts similarity index 82% rename from packages/analytics/shippers/elastic_v3/browser/index.ts rename to packages/analytics/ebt/shippers/elastic_v3/browser/index.ts index 22324dc6d6218..05619fba6e6e3 100644 --- a/packages/analytics/shippers/elastic_v3/browser/index.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/browser/index.ts @@ -6,5 +6,5 @@ * Side Public License, v 1. */ -export type { ElasticV3ShipperOptions } from '@kbn/analytics-shippers-elastic-v3-common'; +export type { ElasticV3ShipperOptions } from '../common'; export { ElasticV3BrowserShipper } from './src/browser_shipper'; diff --git a/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts b/packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.test.ts similarity index 51% rename from packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts rename to packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.test.ts index dca98bddaa6ce..fd8d7f680fd3c 100644 --- a/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.test.ts @@ -7,9 +7,8 @@ */ import { loggerMock } from '@kbn/logging-mocks'; -import type { AnalyticsClientInitContext, Event } from '@kbn/analytics-client'; -import { fakeSchedulers } from 'rxjs-marbles/jest'; import { firstValueFrom } from 'rxjs'; +import type { AnalyticsClientInitContext, Event } from '../../../../client'; import { ElasticV3BrowserShipper } from './browser_shipper'; describe('ElasticV3BrowserShipper', () => { @@ -33,7 +32,7 @@ describe('ElasticV3BrowserShipper', () => { let fetchMock: jest.Mock; beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); + jest.useFakeTimers(); fetchMock = jest.fn().mockResolvedValue({ status: 200, @@ -109,37 +108,32 @@ describe('ElasticV3BrowserShipper', () => { expect(fetchMock).not.toHaveBeenCalled(); }); - test( - 'calls to reportEvents do not call `fetch` after 1s because no optIn value is set yet', - fakeSchedulers((advance) => { - shipper.reportEvents(events); - advance(1000); - expect(fetchMock).not.toHaveBeenCalled(); - }) - ); - - test( - 'calls to reportEvents call `fetch` after 1s when optIn value is set to true', - fakeSchedulers(async (advance) => { - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - advance(1000); - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - keepalive: true, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` + test('calls to reportEvents do not call `fetch` after 1s because no optIn value is set yet', async () => { + shipper.reportEvents(events); + await jest.advanceTimersByTimeAsync(1000); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test('calls to reportEvents call `fetch` after 1s when optIn value is set to true', async () => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + await jest.advanceTimersByTimeAsync(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` Object { "code": "200", "count": 1, @@ -148,43 +142,35 @@ describe('ElasticV3BrowserShipper', () => { "type": "succeeded", } `); - }) - ); - - test( - 'calls to reportEvents do not call `fetch` after 1s when optIn value is set to false', - fakeSchedulers((advance) => { - shipper.reportEvents(events); - shipper.optIn(false); - advance(1000); - expect(fetchMock).not.toHaveBeenCalled(); - }) - ); - - test( - 'calls to flush forces the client to send all the pending events', - fakeSchedulers(async (advance) => { - shipper.optIn(true); - shipper.reportEvents(events); - const counter = firstValueFrom(shipper.telemetryCounter$); - const promise = shipper.flush(); - advance(0); // bufferWhen requires some sort of fake scheduling to advance (but we are not advancing 1s) - await promise; - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - keepalive: true, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` + }); + + test('calls to reportEvents do not call `fetch` after 1s when optIn value is set to false', async () => { + shipper.reportEvents(events); + shipper.optIn(false); + await jest.advanceTimersByTimeAsync(1000); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test('calls to flush forces the client to send all the pending events', async () => { + shipper.optIn(true); + shipper.reportEvents(events); + const counter = firstValueFrom(shipper.telemetryCounter$); + await shipper.flush(); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` Object { "code": "200", "count": 1, @@ -193,8 +179,7 @@ describe('ElasticV3BrowserShipper', () => { "type": "succeeded", } `); - }) - ); + }); test('calls to flush resolve immediately if there is nothing to send', async () => { shipper.optIn(true); @@ -243,55 +228,50 @@ describe('ElasticV3BrowserShipper', () => { `); }); - test( - 'does not add the query.debug: true property to the request if the shipper is not set with the debug flag', - fakeSchedulers((advance) => { - shipper = new ElasticV3BrowserShipper( - { version: '1.2.3', channelName: 'test-channel' }, - initContext - ); - shipper.reportEvents(events); - shipper.optIn(true); - advance(1000); - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - keepalive: true, - method: 'POST', - } - ); - }) - ); - - test( - 'handles when the fetch request fails', - fakeSchedulers(async (advance) => { - fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - advance(1000); - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - keepalive: true, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` + test('does not add the query.debug: true property to the request if the shipper is not set with the debug flag', async () => { + shipper = new ElasticV3BrowserShipper( + { version: '1.2.3', channelName: 'test-channel' }, + initContext + ); + shipper.reportEvents(events); + shipper.optIn(true); + await jest.advanceTimersByTimeAsync(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + } + ); + }); + + test('handles when the fetch request fails', async () => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + await jest.advanceTimersByTimeAsync(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` Object { "code": "Failed to fetch", "count": 1, @@ -300,36 +280,33 @@ describe('ElasticV3BrowserShipper', () => { "type": "failed", } `); - }) - ); - - test( - 'handles when the fetch request fails (request completes but not OK response)', - fakeSchedulers(async (advance) => { - fetchMock.mockResolvedValue({ - ok: false, - status: 400, - text: () => Promise.resolve('{"status": "not ok"}'), - }); - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - advance(1000); - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - keepalive: true, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` + }); + + test('handles when the fetch request fails (request completes but not OK response)', async () => { + fetchMock.mockResolvedValue({ + ok: false, + status: 400, + text: () => Promise.resolve('{"status": "not ok"}'), + }); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + await jest.advanceTimersByTimeAsync(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` Object { "code": "400", "count": 1, @@ -338,6 +315,5 @@ describe('ElasticV3BrowserShipper', () => { "type": "failed", } `); - }) - ); + }); }); diff --git a/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts b/packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts similarity index 95% rename from packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts rename to packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts index 185ce37072be0..c063dcf86a95f 100644 --- a/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts @@ -23,14 +23,9 @@ import type { EventContext, IShipper, TelemetryCounter, -} from '@kbn/analytics-client'; -import { ElasticV3ShipperOptions, ErrorWithCode } from '@kbn/analytics-shippers-elastic-v3-common'; -import { - buildHeaders, - buildUrl, - createTelemetryCounterHelper, - eventsToNDJSON, -} from '@kbn/analytics-shippers-elastic-v3-common'; +} from '../../../../client'; +import { ElasticV3ShipperOptions, ErrorWithCode } from '../../common'; +import { buildHeaders, buildUrl, createTelemetryCounterHelper, eventsToNDJSON } from '../../common'; /** * Elastic V3 shipper to use in the browser. diff --git a/packages/analytics/shippers/elastic_v3/common/README.md b/packages/analytics/ebt/shippers/elastic_v3/common/README.md similarity index 73% rename from packages/analytics/shippers/elastic_v3/common/README.md rename to packages/analytics/ebt/shippers/elastic_v3/common/README.md index 6684027b1ed7f..f212c75961d86 100644 --- a/packages/analytics/shippers/elastic_v3/common/README.md +++ b/packages/analytics/ebt/shippers/elastic_v3/common/README.md @@ -1,4 +1,4 @@ -# @kbn/analytics-shippers-elastic-v3-common +# @kbn/ebt/shippers/elastic_v3/common This package holds the common code for the Elastic V3 shippers: @@ -7,4 +7,4 @@ This package holds the common code for the Elastic V3 shippers: - `eventsToNdjson` utility converts any array of events to NDJSON format. - `reportTelemetryCounters` helps with building the TelemetryCounter to emit after processing an event. -It should be considered an internal package and should not be used other than by the shipper implementations: `@kbn/analytics-shippers-elastic-v3-browser` and `@kbn/analytics-shippers-elastic-v3-server` +It should be considered an internal package and should not be used other than by the shipper implementations: `@kbn/ebt/shippers/elastic_v3/browser` and `@kbn/ebt/shippers/elastic_v3/server` diff --git a/packages/analytics/shippers/elastic_v3/common/index.ts b/packages/analytics/ebt/shippers/elastic_v3/common/index.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/index.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/index.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_headers.test.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/build_headers.test.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/build_headers.test.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/build_headers.test.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_headers.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/build_headers.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/build_headers.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/build_headers.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_url.test.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/build_url.test.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/build_url.test.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/build_url.test.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_url.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/build_url.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/build_url.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/build_url.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/error_with_code.test.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/error_with_code.test.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/error_with_code.test.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/error_with_code.test.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/error_with_code.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/error_with_code.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/error_with_code.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/error_with_code.ts diff --git a/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/events_to_ndjson.test.ts similarity index 96% rename from packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/events_to_ndjson.test.ts index 4033bcb862967..c9bcb58bb1977 100644 --- a/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/common/src/events_to_ndjson.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { Event } from '@kbn/analytics-client'; +import type { Event } from '../../../../client'; import { eventsToNDJSON } from './events_to_ndjson'; describe('eventsToNDJSON', () => { diff --git a/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/events_to_ndjson.ts similarity index 92% rename from packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/events_to_ndjson.ts index f5dc22ff84117..bfd5aabc1223a 100644 --- a/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/common/src/events_to_ndjson.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { Event } from '@kbn/analytics-client'; +import type { Event } from '../../../../client'; /** * Converts an array of events to a single ndjson string. diff --git a/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts similarity index 98% rename from packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts index 33cba78f8b297..a720a0c0129a6 100644 --- a/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts @@ -7,7 +7,7 @@ */ import { firstValueFrom, Subject, take, toArray } from 'rxjs'; -import type { Event, TelemetryCounter } from '@kbn/analytics-client'; +import type { Event, TelemetryCounter } from '../../../../client'; import { createTelemetryCounterHelper } from './report_telemetry_counters'; describe('reportTelemetryCounters', () => { diff --git a/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/report_telemetry_counters.ts similarity index 98% rename from packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/report_telemetry_counters.ts index 36deae1732f7a..68260e653e78d 100644 --- a/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/common/src/report_telemetry_counters.ts @@ -7,7 +7,7 @@ */ import type { Subject } from 'rxjs'; -import type { Event, TelemetryCounter, TelemetryCounterType } from '@kbn/analytics-client'; +import type { Event, TelemetryCounter, TelemetryCounterType } from '../../../../client'; /** * Creates a telemetry counter helper to make it easier to generate them diff --git a/packages/analytics/shippers/elastic_v3/common/src/types.ts b/packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/common/src/types.ts rename to packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts diff --git a/packages/analytics/shippers/elastic_v3/server/README.md b/packages/analytics/ebt/shippers/elastic_v3/server/README.md similarity index 83% rename from packages/analytics/shippers/elastic_v3/server/README.md rename to packages/analytics/ebt/shippers/elastic_v3/server/README.md index edb4bdffa0dba..0c27cef5a0023 100644 --- a/packages/analytics/shippers/elastic_v3/server/README.md +++ b/packages/analytics/ebt/shippers/elastic_v3/server/README.md @@ -1,13 +1,13 @@ -# @kbn/analytics-shippers-elastic-v3-server +# @kbn/ebt/shippers/elastic_v3/server -Server-side implementation of the Elastic V3 shipper for the `@kbn/analytics-client`. +Server-side implementation of the Elastic V3 shipper for the `@kbn/ebt/client`. ## How to use it -This module is intended to be used **on the server-side only**. It is specially designed to apply the necessary backpressure mechanisms to prevent the server from getting overloaded with too many events and identify if the server sits behind a firewall to discard any incoming events. Refer to `@kbn/analytics-shippers-elastic-v3-browser` for the browser-side implementation. +This module is intended to be used **on the server-side only**. It is specially designed to apply the necessary backpressure mechanisms to prevent the server from getting overloaded with too many events and identify if the server sits behind a firewall to discard any incoming events. Refer to `@kbn/ebt/shippers/elastic_v3/browser` for the browser-side implementation. ```typescript -import { ElasticV3ServerShipper } from "@kbn/analytics-shippers-elastic-v3-server"; +import { ElasticV3ServerShipper } from "@kbn/ebt/shippers/elastic_v3/server"; analytics.registerShipper(ElasticV3ServerShipper, { channelName: 'myChannel', version: '1.0.0' }); ``` diff --git a/packages/analytics/shippers/elastic_v3/server/index.ts b/packages/analytics/ebt/shippers/elastic_v3/server/index.ts similarity index 82% rename from packages/analytics/shippers/elastic_v3/server/index.ts rename to packages/analytics/ebt/shippers/elastic_v3/server/index.ts index d5d0cb04a21ed..c0031aac4b217 100644 --- a/packages/analytics/shippers/elastic_v3/server/index.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/server/index.ts @@ -6,5 +6,5 @@ * Side Public License, v 1. */ -export type { ElasticV3ShipperOptions } from '@kbn/analytics-shippers-elastic-v3-common'; +export type { ElasticV3ShipperOptions } from '../common'; export { ElasticV3ServerShipper } from './src/server_shipper'; diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts b/packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts similarity index 100% rename from packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts rename to packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts diff --git a/packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.test.ts b/packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.test.ts new file mode 100644 index 0000000000000..1e973ed4c9819 --- /dev/null +++ b/packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.test.ts @@ -0,0 +1,571 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { loggerMock } from '@kbn/logging-mocks'; +import { firstValueFrom } from 'rxjs'; +import type { AnalyticsClientInitContext, Event } from '../../../../client'; +import { fetchMock } from './server_shipper.test.mocks'; +import { ElasticV3ServerShipper } from './server_shipper'; + +const SECONDS = 1000; +const MINUTES = 60 * SECONDS; + +describe('ElasticV3ServerShipper', () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'test-event-type', + context: {}, + properties: {}, + }, + ]; + + const initContext: AnalyticsClientInitContext = { + sendTo: 'staging', + isDev: true, + logger: loggerMock.create(), + }; + + let shipper: ElasticV3ServerShipper; + + // eslint-disable-next-line dot-notation + const setLastBatchSent = (ms: number) => (shipper['lastBatchSent'] = ms); + + beforeEach(() => { + jest.useFakeTimers({ legacyFakeTimers: false }); + + shipper = new ElasticV3ServerShipper( + { version: '1.2.3', channelName: 'test-channel', debug: true }, + initContext + ); + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = null; // The tests think connectivity is OK initially for easier testing. + }); + + afterEach(() => { + shipper.shutdown(); + jest.clearAllMocks(); + }); + + test('set optIn should update the isOptedIn$ observable', () => { + // eslint-disable-next-line dot-notation + const getInternalOptIn = () => shipper['isOptedIn$'].value; + + // Initially undefined + expect(getInternalOptIn()).toBeUndefined(); + + shipper.optIn(true); + expect(getInternalOptIn()).toBe(true); + + shipper.optIn(false); + expect(getInternalOptIn()).toBe(false); + }); + + test('clears the queue after optIn: false', () => { + shipper.reportEvents(events); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1); + + shipper.optIn(false); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + }); + + test('set extendContext should store local values: clusterUuid and licenseId', () => { + // eslint-disable-next-line dot-notation + const getInternalClusterUuid = () => shipper['clusterUuid']; + // eslint-disable-next-line dot-notation + const getInternalLicenseId = () => shipper['licenseId']; + + // Initial values + expect(getInternalClusterUuid()).toBe('UNKNOWN'); + expect(getInternalLicenseId()).toBeUndefined(); + + shipper.extendContext({ cluster_uuid: 'test-cluster-uuid' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); + expect(getInternalLicenseId()).toBeUndefined(); + + shipper.extendContext({ license_id: 'test-license-id' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); + expect(getInternalLicenseId()).toBe('test-license-id'); + + shipper.extendContext({ cluster_uuid: 'test-cluster-uuid-2', license_id: 'test-license-id-2' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid-2'); + expect(getInternalLicenseId()).toBe('test-license-id-2'); + }); + + test('calls to reportEvents do not call `fetch` straight away', () => { + shipper.reportEvents(events); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test('calls to reportEvents do not call `fetch` after 10 minutes because no optIn value is set yet', async () => { + shipper.reportEvents(events); + await jest.advanceTimersByTimeAsync(10 * MINUTES); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test('calls to reportEvents call `fetch` after 10 seconds when optIn value is set to true', async () => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "succeeded", + } + `); + }); + + test('calls to reportEvents do not call `fetch` after 10 seconds when optIn value is set to false', async () => { + shipper.reportEvents(events); + shipper.optIn(false); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test('calls to reportEvents call `fetch` when shutting down if optIn value is set to true', async () => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + shipper.shutdown(); + jest.advanceTimersToNextTimer(); // We are handling the shutdown in a promise, so we need to wait for the next tick. + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "succeeded", + } + `); + }); + + test('does not add the query.debug: true property to the request if the shipper is not set with the debug flag', async () => { + shipper = new ElasticV3ServerShipper( + { version: '1.2.3', channelName: 'test-channel' }, + initContext + ); + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = null; + shipper.reportEvents(events); + shipper.optIn(true); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + } + ); + }); + + test('sends when the queue overflows the 10kB leaky bucket one batch every 10s', async () => { + expect.assertions(2 * 9 + 2); + + shipper.reportEvents(new Array(1000).fill(events[0])); + shipper.optIn(true); + + // Due to the size of the test events, it matches 8 rounds. + for (let i = 0; i < 9; i++) { + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).toHaveBeenNthCalledWith( + i + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: new Array(103) + .fill( + '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n' + ) + .join(''), + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 103, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "succeeded", + } + `); + jest.advanceTimersToNextTimer(); + } + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1000 - 9 * 103); // 73 + + // If we call it again, it should not enqueue all the events (only the ones to fill the queue): + shipper.reportEvents(new Array(1000).fill(events[0])); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1000); + }); + + test('handles when the fetch request fails', async () => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "Failed to fetch", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "failed", + } + `); + }); + + test('handles when the fetch request fails (request completes but not OK response)', async () => { + fetchMock.mockResolvedValueOnce({ + ok: false, + status: 400, + text: () => Promise.resolve('{"status": "not ok"}'), + }); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "400", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "failed", + } + `); + }); + + describe('Connectivity Checks', () => { + describe('connectivity check when connectivity is confirmed (firstTimeOffline === null)', () => { + test.each([undefined, false, true])('does not run for opt-in %p', async (optInValue) => { + if (optInValue !== undefined) { + shipper.optIn(optInValue); + } + + // From the start, it doesn't check connectivity because already confirmed + expect(fetchMock).not.toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + + // Wait a big time (1 minute should be enough, but for the sake of tests...) + await jest.advanceTimersByTimeAsync(10 * MINUTES); + + expect(fetchMock).not.toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + }); + + describe('connectivity check with initial unknown state of the connectivity', () => { + beforeEach(() => { + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = undefined; // Initial unknown state of the connectivity + }); + + test.each([undefined, false])('does not run for opt-in %p', async (optInValue) => { + if (optInValue !== undefined) { + shipper.optIn(optInValue); + } + + // From the start, it doesn't check connectivity because already confirmed + expect(fetchMock).not.toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + + // Wait a big time (1 minute should be enough, but for the sake of tests...) + await jest.advanceTimersByTimeAsync(10 * MINUTES); + + expect(fetchMock).not.toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + + test('runs as soon as opt-in is set to true', () => { + shipper.optIn(true); + + // From the start, it doesn't check connectivity because opt-in is not true + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + }); + + describe('connectivity check with the connectivity confirmed to be faulty', () => { + beforeEach(() => { + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = 100; // Failed at some point + }); + + test.each([undefined, false])('does not run for opt-in %p', async (optInValue) => { + if (optInValue !== undefined) { + shipper.optIn(optInValue); + } + + // From the start, it doesn't check connectivity because already confirmed + expect(fetchMock).not.toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + + // Wait a big time (1 minute should be enough, but for the sake of tests...) + await jest.advanceTimersByTimeAsync(10 * MINUTES); + + expect(fetchMock).not.toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + + test('runs as soon as opt-in is set to true', () => { + shipper.optIn(true); + + // From the start, it doesn't check connectivity because opt-in is not true + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + }); + + describe('after report failure', () => { + // generate the report failure for each test + beforeEach(async () => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * SECONDS); + await jest.advanceTimersByTimeAsync(1 * SECONDS); // Moving 1 second should be enough to trigger the logic + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "Failed to fetch", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "failed", + } + `); + }); + + test('connectivity check runs periodically', async () => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + await jest.advanceTimersByTimeAsync(1 * MINUTES); + expect(fetchMock).toHaveBeenNthCalledWith( + 2, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + fetchMock.mockResolvedValueOnce({ ok: false }); + await jest.advanceTimersByTimeAsync(2 * MINUTES); + expect(fetchMock).toHaveBeenNthCalledWith( + 3, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + }); + + describe('after being offline for longer than 24h', () => { + beforeEach(() => { + shipper.optIn(true); + shipper.reportEvents(events); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1); + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = 100; + }); + + test('the following connectivity check clears the queue', async () => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + await jest.advanceTimersByTimeAsync(1 * MINUTES); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + }); + + test('new events are not added to the queue', async () => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + await jest.advanceTimersByTimeAsync(1 * MINUTES); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + + shipper.reportEvents(events); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + }); + + test('regains the connection', async () => { + fetchMock.mockResolvedValueOnce({ ok: true }); + await jest.advanceTimersByTimeAsync(1 * MINUTES); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + // eslint-disable-next-line dot-notation + expect(shipper['firstTimeOffline']).toBe(null); + + await jest.advanceTimersByTimeAsync(10 * MINUTES); + expect(fetchMock).not.toHaveBeenNthCalledWith( + 2, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }); + }); + }); + + describe('flush method', () => { + test('resolves straight away if it should not send anything', async () => { + await expect(shipper.flush()).resolves.toBe(undefined); + }); + + test('resolves when all the ongoing requests are complete', async () => { + shipper.optIn(true); + shipper.reportEvents(events); + expect(fetchMock).toHaveBeenCalledTimes(0); + fetchMock.mockImplementation(async () => { + // eslint-disable-next-line dot-notation + expect(shipper['inFlightRequests$'].value).toBe(1); + }); + await expect(shipper.flush()).resolves.toBe(undefined); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + }); + + test('calling flush multiple times does not keep hanging', async () => { + await expect(shipper.flush()).resolves.toBe(undefined); + await expect(shipper.flush()).resolves.toBe(undefined); + await Promise.all([shipper.flush(), shipper.flush()]); + }); + + test('calling flush after shutdown does not keep hanging', async () => { + shipper.shutdown(); + await expect(shipper.flush()).resolves.toBe(undefined); + }); + }); +}); diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts b/packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts similarity index 99% rename from packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts rename to packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts index cb6e689dd893f..d3b54da3314cf 100644 --- a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts +++ b/packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts @@ -25,13 +25,6 @@ import { skip, firstValueFrom, } from 'rxjs'; -import type { - AnalyticsClientInitContext, - Event, - EventContext, - IShipper, - TelemetryCounter, -} from '@kbn/analytics-client'; import { type ElasticV3ShipperOptions, buildHeaders, @@ -39,7 +32,14 @@ import { createTelemetryCounterHelper, eventsToNDJSON, ErrorWithCode, -} from '@kbn/analytics-shippers-elastic-v3-common'; +} from '../../common'; +import type { + AnalyticsClientInitContext, + Event, + EventContext, + IShipper, + TelemetryCounter, +} from '../../../../client'; const SECOND = 1000; const MINUTE = 60 * SECOND; diff --git a/packages/analytics/shippers/fullstory/README.md b/packages/analytics/ebt/shippers/fullstory/README.md similarity index 91% rename from packages/analytics/shippers/fullstory/README.md rename to packages/analytics/ebt/shippers/fullstory/README.md index 6d1c443db3d22..a1e557a7600b8 100644 --- a/packages/analytics/shippers/fullstory/README.md +++ b/packages/analytics/ebt/shippers/fullstory/README.md @@ -1,13 +1,13 @@ -# @kbn/analytics-shippers-fullstory +# @kbn/ebt/shippers/fullstory -FullStory implementation as a shipper for the `@kbn/analytics-client`. +FullStory implementation as a shipper for the `@kbn/ebt/client`. ## How to use it This module is intended to be used **on the browser only**. It does not support server-side events. ```typescript -import { FullStoryShipper } from "@kbn/analytics-shippers-fullstory"; +import { FullStoryShipper } from "@kbn/ebt/shippers/fullstory"; analytics.registerShipper(FullStoryShipper, { fullStoryOrgId: '12345' }) ``` diff --git a/packages/analytics/shippers/fullstory/index.ts b/packages/analytics/ebt/shippers/fullstory/index.ts similarity index 100% rename from packages/analytics/shippers/fullstory/index.ts rename to packages/analytics/ebt/shippers/fullstory/index.ts diff --git a/packages/analytics/shippers/fullstory/src/format_payload.test.ts b/packages/analytics/ebt/shippers/fullstory/src/format_payload.test.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/format_payload.test.ts rename to packages/analytics/ebt/shippers/fullstory/src/format_payload.test.ts diff --git a/packages/analytics/shippers/fullstory/src/format_payload.ts b/packages/analytics/ebt/shippers/fullstory/src/format_payload.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/format_payload.ts rename to packages/analytics/ebt/shippers/fullstory/src/format_payload.ts diff --git a/packages/analytics/shippers/fullstory/src/fullstory_shipper.test.mocks.ts b/packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.test.mocks.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/fullstory_shipper.test.mocks.ts rename to packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.test.mocks.ts diff --git a/packages/analytics/shippers/fullstory/src/fullstory_shipper.test.ts b/packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.test.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/fullstory_shipper.test.ts rename to packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.test.ts diff --git a/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts b/packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts similarity index 96% rename from packages/analytics/shippers/fullstory/src/fullstory_shipper.ts rename to packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts index 96ae3389be017..a091076236a80 100644 --- a/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts +++ b/packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts @@ -6,15 +6,10 @@ * Side Public License, v 1. */ -import type { - AnalyticsClientInitContext, - EventContext, - Event, - IShipper, -} from '@kbn/analytics-client'; import { Subject, distinct, debounceTime, map, filter, Subscription } from 'rxjs'; import { get, has } from 'lodash'; import { set } from '@kbn/safer-lodash-set'; +import type { AnalyticsClientInitContext, EventContext, Event, IShipper } from '../../../client'; import type { FullStoryApi } from './types'; import type { FullStorySnippetConfig } from './load_snippet'; import { formatPayload } from './format_payload'; @@ -56,6 +51,10 @@ export interface FullStoryShipperConfig extends FullStorySnippetConfig { * If this setting is provided, it'll only send the event types specified in this list. */ eventTypesAllowlist?: string[]; + /** + * FullStory only allows calling setVars('page') once per navigation. + * This setting defines how much time to hold from calling the API while additional lazy context is being resolved. + */ pageVarsDebounceTimeMs?: number; } diff --git a/packages/analytics/shippers/fullstory/src/get_parsed_version.test.ts b/packages/analytics/ebt/shippers/fullstory/src/get_parsed_version.test.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/get_parsed_version.test.ts rename to packages/analytics/ebt/shippers/fullstory/src/get_parsed_version.test.ts diff --git a/packages/analytics/shippers/fullstory/src/get_parsed_version.ts b/packages/analytics/ebt/shippers/fullstory/src/get_parsed_version.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/get_parsed_version.ts rename to packages/analytics/ebt/shippers/fullstory/src/get_parsed_version.ts diff --git a/packages/analytics/shippers/fullstory/src/load_snippet.test.ts b/packages/analytics/ebt/shippers/fullstory/src/load_snippet.test.ts similarity index 68% rename from packages/analytics/shippers/fullstory/src/load_snippet.test.ts rename to packages/analytics/ebt/shippers/fullstory/src/load_snippet.test.ts index 0b920ef2d22c1..002f113f71f63 100644 --- a/packages/analytics/shippers/fullstory/src/load_snippet.test.ts +++ b/packages/analytics/ebt/shippers/fullstory/src/load_snippet.test.ts @@ -11,25 +11,11 @@ import { loadSnippet } from './load_snippet'; describe('loadSnippet', () => { beforeAll(() => { // Define necessary window and document global variables for the tests - Object.defineProperty(global, 'window', { - writable: true, - value: {}, - }); - - Object.defineProperty(global, 'document', { - writable: true, - value: { - createElement: jest.fn().mockReturnValue({}), - getElementsByTagName: jest - .fn() - .mockReturnValue([{ parentNode: { insertBefore: jest.fn() } }]), - }, - }); - - Object.defineProperty(global, '_fs_script', { - writable: true, - value: '', - }); + jest + .spyOn(global.document, 'getElementsByTagName') + .mockReturnValue([ + { parentNode: { insertBefore: jest.fn() } }, + ] as unknown as HTMLCollectionOf); }); it('should return the FullStory API', () => { diff --git a/packages/analytics/shippers/fullstory/src/load_snippet.ts b/packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/load_snippet.ts rename to packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts diff --git a/packages/analytics/shippers/fullstory/src/types.ts b/packages/analytics/ebt/shippers/fullstory/src/types.ts similarity index 100% rename from packages/analytics/shippers/fullstory/src/types.ts rename to packages/analytics/ebt/shippers/fullstory/src/types.ts diff --git a/packages/analytics/client/tsconfig.json b/packages/analytics/ebt/tsconfig.json similarity index 63% rename from packages/analytics/client/tsconfig.json rename to packages/analytics/ebt/tsconfig.json index b5bb1c1f7c010..38e6caee5d2a1 100644 --- a/packages/analytics/client/tsconfig.json +++ b/packages/analytics/ebt/tsconfig.json @@ -4,17 +4,20 @@ "outDir": "target/types", "types": [ "jest", - "node" + "node", + "react" ] }, "include": [ - "**/*.ts" + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" ], "kbn_references": [ + "@kbn/logging-mocks", "@kbn/logging", - "@kbn/logging-mocks" - ], - "exclude": [ - "target/**/*", + "@kbn/safer-lodash-set", ] } diff --git a/packages/analytics/shippers/elastic_v3/browser/jest.config.js b/packages/analytics/shippers/elastic_v3/browser/jest.config.js deleted file mode 100644 index 20067863aad97..0000000000000 --- a/packages/analytics/shippers/elastic_v3/browser/jest.config.js +++ /dev/null @@ -1,13 +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. - */ - -module.exports = { - preset: '@kbn/test/jest_node', - rootDir: '../../../../../', - roots: ['/packages/analytics/shippers/elastic_v3/browser'], -}; diff --git a/packages/analytics/shippers/elastic_v3/browser/kibana.jsonc b/packages/analytics/shippers/elastic_v3/browser/kibana.jsonc deleted file mode 100644 index a54bd23df252d..0000000000000 --- a/packages/analytics/shippers/elastic_v3/browser/kibana.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/analytics-shippers-elastic-v3-browser", - "owner": "@elastic/kibana-core" -} diff --git a/packages/analytics/shippers/elastic_v3/browser/package.json b/packages/analytics/shippers/elastic_v3/browser/package.json deleted file mode 100644 index 88d42d1fd184b..0000000000000 --- a/packages/analytics/shippers/elastic_v3/browser/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/analytics-shippers-elastic-v3-browser", - "private": true, - "version": "1.0.0", - "author": "Kibana Core", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/analytics/shippers/elastic_v3/browser/tsconfig.json b/packages/analytics/shippers/elastic_v3/browser/tsconfig.json deleted file mode 100644 index 7808dee7058f0..0000000000000 --- a/packages/analytics/shippers/elastic_v3/browser/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/analytics-client", - "@kbn/analytics-shippers-elastic-v3-common", - "@kbn/logging-mocks" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/analytics/shippers/elastic_v3/common/jest.config.js b/packages/analytics/shippers/elastic_v3/common/jest.config.js deleted file mode 100644 index 1336211347fb7..0000000000000 --- a/packages/analytics/shippers/elastic_v3/common/jest.config.js +++ /dev/null @@ -1,13 +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. - */ - -module.exports = { - preset: '@kbn/test/jest_node', - rootDir: '../../../../../', - roots: ['/packages/analytics/shippers/elastic_v3/common'], -}; diff --git a/packages/analytics/shippers/elastic_v3/common/kibana.jsonc b/packages/analytics/shippers/elastic_v3/common/kibana.jsonc deleted file mode 100644 index 30c723c2b5217..0000000000000 --- a/packages/analytics/shippers/elastic_v3/common/kibana.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/analytics-shippers-elastic-v3-common", - "owner": "@elastic/kibana-core" -} diff --git a/packages/analytics/shippers/elastic_v3/common/package.json b/packages/analytics/shippers/elastic_v3/common/package.json deleted file mode 100644 index 4e1caaf0d6a2f..0000000000000 --- a/packages/analytics/shippers/elastic_v3/common/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/analytics-shippers-elastic-v3-common", - "private": true, - "version": "1.0.0", - "author": "Kibana Core", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/analytics/shippers/elastic_v3/common/tsconfig.json b/packages/analytics/shippers/elastic_v3/common/tsconfig.json deleted file mode 100644 index 698191a0c3816..0000000000000 --- a/packages/analytics/shippers/elastic_v3/common/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/analytics-client" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/analytics/shippers/elastic_v3/server/jest.config.js b/packages/analytics/shippers/elastic_v3/server/jest.config.js deleted file mode 100644 index 4397eb3e50c5a..0000000000000 --- a/packages/analytics/shippers/elastic_v3/server/jest.config.js +++ /dev/null @@ -1,13 +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. - */ - -module.exports = { - preset: '@kbn/test/jest_node', - rootDir: '../../../../../', - roots: ['/packages/analytics/shippers/elastic_v3/server'], -}; diff --git a/packages/analytics/shippers/elastic_v3/server/kibana.jsonc b/packages/analytics/shippers/elastic_v3/server/kibana.jsonc deleted file mode 100644 index a516db1bbf30e..0000000000000 --- a/packages/analytics/shippers/elastic_v3/server/kibana.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/analytics-shippers-elastic-v3-server", - "owner": "@elastic/kibana-core" -} diff --git a/packages/analytics/shippers/elastic_v3/server/package.json b/packages/analytics/shippers/elastic_v3/server/package.json deleted file mode 100644 index 3fcbd5062d35f..0000000000000 --- a/packages/analytics/shippers/elastic_v3/server/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/analytics-shippers-elastic-v3-server", - "private": true, - "version": "1.0.0", - "author": "Kibana Core", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts deleted file mode 100644 index 1d5ab760d15f2..0000000000000 --- a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts +++ /dev/null @@ -1,624 +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 { loggerMock } from '@kbn/logging-mocks'; -import { firstValueFrom } from 'rxjs'; -import { fakeSchedulers } from 'rxjs-marbles/jest'; -import type { AnalyticsClientInitContext, Event } from '@kbn/analytics-client'; -import { fetchMock } from './server_shipper.test.mocks'; -import { ElasticV3ServerShipper } from './server_shipper'; - -const SECONDS = 1000; -const MINUTES = 60 * SECONDS; - -describe('ElasticV3ServerShipper', () => { - const events: Event[] = [ - { - timestamp: '2020-01-01T00:00:00.000Z', - event_type: 'test-event-type', - context: {}, - properties: {}, - }, - ]; - - const nextTick = () => new Promise((resolve) => setImmediate(resolve)); - - const initContext: AnalyticsClientInitContext = { - sendTo: 'staging', - isDev: true, - logger: loggerMock.create(), - }; - - let shipper: ElasticV3ServerShipper; - - // eslint-disable-next-line dot-notation - const setLastBatchSent = (ms: number) => (shipper['lastBatchSent'] = ms); - - beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); - - shipper = new ElasticV3ServerShipper( - { version: '1.2.3', channelName: 'test-channel', debug: true }, - initContext - ); - // eslint-disable-next-line dot-notation - shipper['firstTimeOffline'] = null; // The tests think connectivity is OK initially for easier testing. - }); - - afterEach(() => { - shipper.shutdown(); - jest.clearAllMocks(); - }); - - test('set optIn should update the isOptedIn$ observable', () => { - // eslint-disable-next-line dot-notation - const getInternalOptIn = () => shipper['isOptedIn$'].value; - - // Initially undefined - expect(getInternalOptIn()).toBeUndefined(); - - shipper.optIn(true); - expect(getInternalOptIn()).toBe(true); - - shipper.optIn(false); - expect(getInternalOptIn()).toBe(false); - }); - - test('clears the queue after optIn: false', () => { - shipper.reportEvents(events); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(1); - - shipper.optIn(false); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(0); - }); - - test('set extendContext should store local values: clusterUuid and licenseId', () => { - // eslint-disable-next-line dot-notation - const getInternalClusterUuid = () => shipper['clusterUuid']; - // eslint-disable-next-line dot-notation - const getInternalLicenseId = () => shipper['licenseId']; - - // Initial values - expect(getInternalClusterUuid()).toBe('UNKNOWN'); - expect(getInternalLicenseId()).toBeUndefined(); - - shipper.extendContext({ cluster_uuid: 'test-cluster-uuid' }); - expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); - expect(getInternalLicenseId()).toBeUndefined(); - - shipper.extendContext({ license_id: 'test-license-id' }); - expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); - expect(getInternalLicenseId()).toBe('test-license-id'); - - shipper.extendContext({ cluster_uuid: 'test-cluster-uuid-2', license_id: 'test-license-id-2' }); - expect(getInternalClusterUuid()).toBe('test-cluster-uuid-2'); - expect(getInternalLicenseId()).toBe('test-license-id-2'); - }); - - test('calls to reportEvents do not call `fetch` straight away', () => { - shipper.reportEvents(events); - expect(fetchMock).not.toHaveBeenCalled(); - }); - - test( - 'calls to reportEvents do not call `fetch` after 10 minutes because no optIn value is set yet', - fakeSchedulers((advance) => { - shipper.reportEvents(events); - advance(10 * MINUTES); - expect(fetchMock).not.toHaveBeenCalled(); - }) - ); - - test( - 'calls to reportEvents call `fetch` after 10 seconds when optIn value is set to true', - fakeSchedulers(async (advance) => { - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` - Object { - "code": "200", - "count": 1, - "event_type": "test-event-type", - "source": "elastic_v3_server", - "type": "succeeded", - } - `); - }) - ); - - test( - 'calls to reportEvents do not call `fetch` after 10 seconds when optIn value is set to false', - fakeSchedulers((advance) => { - shipper.reportEvents(events); - shipper.optIn(false); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).not.toHaveBeenCalled(); - }) - ); - - test('calls to reportEvents call `fetch` when shutting down if optIn value is set to true', async () => { - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - shipper.shutdown(); - await nextTick(); // We are handling the shutdown in a promise, so we need to wait for the next tick. - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` - Object { - "code": "200", - "count": 1, - "event_type": "test-event-type", - "source": "elastic_v3_server", - "type": "succeeded", - } - `); - }); - - test( - 'does not add the query.debug: true property to the request if the shipper is not set with the debug flag', - fakeSchedulers((advance) => { - shipper = new ElasticV3ServerShipper( - { version: '1.2.3', channelName: 'test-channel' }, - initContext - ); - // eslint-disable-next-line dot-notation - shipper['firstTimeOffline'] = null; - shipper.reportEvents(events); - shipper.optIn(true); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - } - ); - }) - ); - - test( - 'sends when the queue overflows the 10kB leaky bucket one batch every 10s', - fakeSchedulers(async (advance) => { - expect.assertions(2 * 9 + 2); - - shipper.reportEvents(new Array(1000).fill(events[0])); - shipper.optIn(true); - - // Due to the size of the test events, it matches 8 rounds. - for (let i = 0; i < 9; i++) { - const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).toHaveBeenNthCalledWith( - i + 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: new Array(103) - .fill( - '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n' - ) - .join(''), - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` - Object { - "code": "200", - "count": 103, - "event_type": "test-event-type", - "source": "elastic_v3_server", - "type": "succeeded", - } - `); - await nextTick(); - } - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(1000 - 9 * 103); // 73 - - // If we call it again, it should not enqueue all the events (only the ones to fill the queue): - shipper.reportEvents(new Array(1000).fill(events[0])); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(1000); - }) - ); - - test( - 'handles when the fetch request fails', - fakeSchedulers(async (advance) => { - fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` - Object { - "code": "Failed to fetch", - "count": 1, - "event_type": "test-event-type", - "source": "elastic_v3_server", - "type": "failed", - } - `); - }) - ); - - test( - 'handles when the fetch request fails (request completes but not OK response)', - fakeSchedulers(async (advance) => { - fetchMock.mockResolvedValueOnce({ - ok: false, - status: 400, - text: () => Promise.resolve('{"status": "not ok"}'), - }); - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` - Object { - "code": "400", - "count": 1, - "event_type": "test-event-type", - "source": "elastic_v3_server", - "type": "failed", - } - `); - }) - ); - - describe('Connectivity Checks', () => { - describe('connectivity check when connectivity is confirmed (firstTimeOffline === null)', () => { - test.each([undefined, false, true])('does not run for opt-in %p', (optInValue) => - fakeSchedulers(async (advance) => { - if (optInValue !== undefined) { - shipper.optIn(optInValue); - } - - // From the start, it doesn't check connectivity because already confirmed - expect(fetchMock).not.toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - - // Wait a big time (1 minute should be enough, but for the sake of tests...) - advance(10 * MINUTES); - await nextTick(); - - expect(fetchMock).not.toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - })() - ); - }); - - describe('connectivity check with initial unknown state of the connectivity', () => { - beforeEach(() => { - // eslint-disable-next-line dot-notation - shipper['firstTimeOffline'] = undefined; // Initial unknown state of the connectivity - }); - - test.each([undefined, false])('does not run for opt-in %p', (optInValue) => - fakeSchedulers(async (advance) => { - if (optInValue !== undefined) { - shipper.optIn(optInValue); - } - - // From the start, it doesn't check connectivity because already confirmed - expect(fetchMock).not.toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - - // Wait a big time (1 minute should be enough, but for the sake of tests...) - advance(10 * MINUTES); - await nextTick(); - - expect(fetchMock).not.toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - })() - ); - - test('runs as soon as opt-in is set to true', () => { - shipper.optIn(true); - - // From the start, it doesn't check connectivity because opt-in is not true - expect(fetchMock).toHaveBeenNthCalledWith( - 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - }); - }); - - describe('connectivity check with the connectivity confirmed to be faulty', () => { - beforeEach(() => { - // eslint-disable-next-line dot-notation - shipper['firstTimeOffline'] = 100; // Failed at some point - }); - - test.each([undefined, false])('does not run for opt-in %p', (optInValue) => - fakeSchedulers(async (advance) => { - if (optInValue !== undefined) { - shipper.optIn(optInValue); - } - - // From the start, it doesn't check connectivity because already confirmed - expect(fetchMock).not.toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - - // Wait a big time (1 minute should be enough, but for the sake of tests...) - advance(10 * MINUTES); - await nextTick(); - - expect(fetchMock).not.toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - })() - ); - - test('runs as soon as opt-in is set to true', () => { - shipper.optIn(true); - - // From the start, it doesn't check connectivity because opt-in is not true - expect(fetchMock).toHaveBeenNthCalledWith( - 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - }); - }); - - describe('after report failure', () => { - // generate the report failure for each test - beforeEach( - fakeSchedulers(async (advance) => { - fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); - shipper.reportEvents(events); - shipper.optIn(true); - const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * SECONDS); - advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic - expect(fetchMock).toHaveBeenNthCalledWith( - 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - await expect(counter).resolves.toMatchInlineSnapshot(` - Object { - "code": "Failed to fetch", - "count": 1, - "event_type": "test-event-type", - "source": "elastic_v3_server", - "type": "failed", - } - `); - }) - ); - - test( - 'connectivity check runs periodically', - fakeSchedulers(async (advance) => { - fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); - advance(1 * MINUTES); - await nextTick(); - expect(fetchMock).toHaveBeenNthCalledWith( - 2, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - fetchMock.mockResolvedValueOnce({ ok: false }); - advance(2 * MINUTES); - await nextTick(); - expect(fetchMock).toHaveBeenNthCalledWith( - 3, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - }) - ); - }); - - describe('after being offline for longer than 24h', () => { - beforeEach(() => { - shipper.optIn(true); - shipper.reportEvents(events); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(1); - // eslint-disable-next-line dot-notation - shipper['firstTimeOffline'] = 100; - }); - - test( - 'the following connectivity check clears the queue', - fakeSchedulers(async (advance) => { - fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); - advance(1 * MINUTES); - await nextTick(); - expect(fetchMock).toHaveBeenNthCalledWith( - 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(0); - }) - ); - - test( - 'new events are not added to the queue', - fakeSchedulers(async (advance) => { - fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); - advance(1 * MINUTES); - await nextTick(); - expect(fetchMock).toHaveBeenNthCalledWith( - 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(0); - - shipper.reportEvents(events); - // eslint-disable-next-line dot-notation - expect(shipper['internalQueue'].length).toBe(0); - }) - ); - - test( - 'regains the connection', - fakeSchedulers(async (advance) => { - fetchMock.mockResolvedValueOnce({ ok: true }); - advance(1 * MINUTES); - await nextTick(); - expect(fetchMock).toHaveBeenNthCalledWith( - 1, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - // eslint-disable-next-line dot-notation - expect(shipper['firstTimeOffline']).toBe(null); - - advance(10 * MINUTES); - await nextTick(); - expect(fetchMock).not.toHaveBeenNthCalledWith( - 2, - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { method: 'OPTIONS' } - ); - }) - ); - }); - }); - - describe('flush method', () => { - test('resolves straight away if it should not send anything', async () => { - await expect(shipper.flush()).resolves.toBe(undefined); - }); - - test('resolves when all the ongoing requests are complete', async () => { - shipper.optIn(true); - shipper.reportEvents(events); - expect(fetchMock).toHaveBeenCalledTimes(0); - fetchMock.mockImplementation(async () => { - // eslint-disable-next-line dot-notation - expect(shipper['inFlightRequests$'].value).toBe(1); - }); - await expect(shipper.flush()).resolves.toBe(undefined); - expect(fetchMock).toHaveBeenCalledWith( - 'https://telemetry-staging.elastic.co/v3/send/test-channel', - { - body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', - headers: { - 'content-type': 'application/x-ndjson', - 'x-elastic-cluster-id': 'UNKNOWN', - 'x-elastic-stack-version': '1.2.3', - }, - method: 'POST', - query: { debug: true }, - } - ); - }); - - test('calling flush multiple times does not keep hanging', async () => { - await expect(shipper.flush()).resolves.toBe(undefined); - await expect(shipper.flush()).resolves.toBe(undefined); - await Promise.all([shipper.flush(), shipper.flush()]); - }); - - test('calling flush after shutdown does not keep hanging', async () => { - shipper.shutdown(); - await expect(shipper.flush()).resolves.toBe(undefined); - }); - }); -}); diff --git a/packages/analytics/shippers/elastic_v3/server/tsconfig.json b/packages/analytics/shippers/elastic_v3/server/tsconfig.json deleted file mode 100644 index 7808dee7058f0..0000000000000 --- a/packages/analytics/shippers/elastic_v3/server/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/analytics-client", - "@kbn/analytics-shippers-elastic-v3-common", - "@kbn/logging-mocks" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/analytics/shippers/fullstory/jest.config.js b/packages/analytics/shippers/fullstory/jest.config.js deleted file mode 100644 index 9d1637823c150..0000000000000 --- a/packages/analytics/shippers/fullstory/jest.config.js +++ /dev/null @@ -1,13 +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. - */ - -module.exports = { - preset: '@kbn/test/jest_node', - rootDir: '../../../../', - roots: ['/packages/analytics/shippers/fullstory'], -}; diff --git a/packages/analytics/shippers/fullstory/kibana.jsonc b/packages/analytics/shippers/fullstory/kibana.jsonc deleted file mode 100644 index d2848e7b3c453..0000000000000 --- a/packages/analytics/shippers/fullstory/kibana.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/analytics-shippers-fullstory", - "owner": "@elastic/kibana-core" -} diff --git a/packages/analytics/shippers/fullstory/package.json b/packages/analytics/shippers/fullstory/package.json deleted file mode 100644 index 4eca1476236a1..0000000000000 --- a/packages/analytics/shippers/fullstory/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@kbn/analytics-shippers-fullstory", - "private": true, - "version": "1.0.0", - "author": "Kibana Core", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/analytics/shippers/fullstory/tsconfig.json b/packages/analytics/shippers/fullstory/tsconfig.json deleted file mode 100644 index 00a680d9c6f2c..0000000000000 --- a/packages/analytics/shippers/fullstory/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/analytics-client", - "@kbn/logging-mocks", - "@kbn/safer-lodash-set" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts index 7f32ea7ed41a6..ec9d9e05aff23 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { AnalyticsClient } from '@kbn/analytics-client'; +import { AnalyticsClient } from '@kbn/ebt/client'; import { Subject } from 'rxjs'; export const analyticsClientMock: jest.Mocked = { @@ -21,6 +21,6 @@ export const analyticsClientMock: jest.Mocked = { shutdown: jest.fn(), }; -jest.doMock('@kbn/analytics-client', () => ({ +jest.doMock('@kbn/ebt/client', () => ({ createAnalytics: () => analyticsClientMock, })); diff --git a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts index 25ea7aed65afc..091643741331e 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts @@ -7,8 +7,8 @@ */ import { of, Subscription } from 'rxjs'; -import type { AnalyticsClient } from '@kbn/analytics-client'; -import { createAnalytics } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; +import { createAnalytics } from '@kbn/ebt/client'; import { registerPerformanceMetricEventType } from '@kbn/ebt-tools'; import type { CoreContext } from '@kbn/core-base-browser-internal'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; diff --git a/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts b/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts index 6ca58e7d69149..e545ec0fe7b2a 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts @@ -7,7 +7,7 @@ */ import { fromEvent } from 'rxjs'; -import type { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; /** HTML attributes that should be skipped from reporting because they might contain data we do not wish to collect */ const HTML_ATTRIBUTES_TO_REMOVE = [ diff --git a/packages/core/analytics/core-analytics-browser-internal/src/track_performance_measure_entries.ts b/packages/core/analytics/core-analytics-browser-internal/src/track_performance_measure_entries.ts index 80826c03864ad..40d479b448b46 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/track_performance_measure_entries.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/track_performance_measure_entries.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 { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; export function trackPerformanceMeasureEntries(analytics: AnalyticsClient, isDevMode: boolean) { diff --git a/packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts b/packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts index 17fab459f2e8f..dd0ebde28addb 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts @@ -7,7 +7,7 @@ */ import { debounceTime, fromEvent, map, merge, of, shareReplay } from 'rxjs'; -import type { AnalyticsClient, RootSchema } from '@kbn/analytics-client'; +import type { AnalyticsClient, RootSchema } from '@kbn/ebt/client'; export interface ViewportSize { viewport_width: number; diff --git a/packages/core/analytics/core-analytics-browser-internal/tsconfig.json b/packages/core/analytics/core-analytics-browser-internal/tsconfig.json index a58f3402e65a9..ecac1746f44a2 100644 --- a/packages/core/analytics/core-analytics-browser-internal/tsconfig.json +++ b/packages/core/analytics/core-analytics-browser-internal/tsconfig.json @@ -6,13 +6,13 @@ }, "include": ["**/*.ts"], "kbn_references": [ - "@kbn/analytics-client", "@kbn/ebt-tools", "@kbn/core-base-browser-internal", "@kbn/core-injected-metadata-browser-internal", "@kbn/core-analytics-browser", "@kbn/core-base-browser-mocks", "@kbn/core-injected-metadata-browser-mocks", + "@kbn/ebt", ], "exclude": ["target/**/*"] } diff --git a/packages/core/analytics/core-analytics-browser/index.ts b/packages/core/analytics/core-analytics-browser/index.ts index 331f1695d9f20..f20ccf31da2c4 100644 --- a/packages/core/analytics/core-analytics-browser/index.ts +++ b/packages/core/analytics/core-analytics-browser/index.ts @@ -11,3 +11,41 @@ export type { AnalyticsServiceStart, KbnAnalyticsWindowApi, } from './src/types'; + +export type { + AnalyticsClient, + AnalyticsClientInitContext, + // Types for the registerShipper API + ShipperClassConstructor, + RegisterShipperOpts, + // Types for the optIn API + OptInConfig, + OptInConfigPerType, + ShipperName, + // Types for the registerContextProvider API + ContextProviderOpts, + ContextProviderName, + // Types for the registerEventType API + EventTypeOpts, + // Events + Event, + EventContext, + EventType, + TelemetryCounter, + TelemetryCounterType, + // Schema + RootSchema, + SchemaObject, + SchemaArray, + SchemaChildValue, + SchemaMeta, + SchemaValue, + SchemaMetaOptional, + PossibleSchemaTypes, + AllowedSchemaBooleanTypes, + AllowedSchemaNumberTypes, + AllowedSchemaStringTypes, + AllowedSchemaTypes, + // Shippers + IShipper, +} from '@kbn/ebt/client'; diff --git a/packages/core/analytics/core-analytics-browser/src/types.ts b/packages/core/analytics/core-analytics-browser/src/types.ts index dbc35043613cd..779172acc9b9d 100644 --- a/packages/core/analytics/core-analytics-browser/src/types.ts +++ b/packages/core/analytics/core-analytics-browser/src/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; /** * Exposes the public APIs of the AnalyticsClient during the setup phase. diff --git a/packages/core/analytics/core-analytics-browser/tsconfig.json b/packages/core/analytics/core-analytics-browser/tsconfig.json index 9c3a721a57e23..83571abe4bcf4 100644 --- a/packages/core/analytics/core-analytics-browser/tsconfig.json +++ b/packages/core/analytics/core-analytics-browser/tsconfig.json @@ -11,7 +11,7 @@ "**/*.ts" ], "kbn_references": [ - "@kbn/analytics-client" + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts b/packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts index a3bd814f1e32f..d759a9520cc16 100644 --- a/packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts +++ b/packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { AnalyticsClient } from '@kbn/analytics-client'; +import { AnalyticsClient } from '@kbn/ebt/client'; import { Subject } from 'rxjs'; export const analyticsClientMock: jest.Mocked = { @@ -21,6 +21,6 @@ export const analyticsClientMock: jest.Mocked = { flush: jest.fn(), }; -jest.doMock('@kbn/analytics-client', () => ({ +jest.doMock('@kbn/ebt/client', () => ({ createAnalytics: () => analyticsClientMock, })); diff --git a/packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts b/packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts index 141f5b9970c0b..8e0ce76e08b96 100644 --- a/packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts +++ b/packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts @@ -7,8 +7,8 @@ */ import { of } from 'rxjs'; -import type { AnalyticsClient } from '@kbn/analytics-client'; -import { createAnalytics } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; +import { createAnalytics } from '@kbn/ebt/client'; import { registerPerformanceMetricEventType } from '@kbn/ebt-tools'; import type { CoreContext } from '@kbn/core-base-server-internal'; import type { diff --git a/packages/core/analytics/core-analytics-server-internal/tsconfig.json b/packages/core/analytics/core-analytics-server-internal/tsconfig.json index 56292065f7af6..57a0fa3e04362 100644 --- a/packages/core/analytics/core-analytics-server-internal/tsconfig.json +++ b/packages/core/analytics/core-analytics-server-internal/tsconfig.json @@ -11,12 +11,12 @@ "**/*.ts" ], "kbn_references": [ - "@kbn/analytics-client", "@kbn/ebt-tools", "@kbn/core-base-server-internal", "@kbn/core-analytics-server", "@kbn/config-mocks", "@kbn/core-base-server-mocks", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/packages/core/analytics/core-analytics-server/index.ts b/packages/core/analytics/core-analytics-server/index.ts index c9a91ca3a8866..90341deb693a3 100644 --- a/packages/core/analytics/core-analytics-server/index.ts +++ b/packages/core/analytics/core-analytics-server/index.ts @@ -11,3 +11,41 @@ export type { AnalyticsServiceStart, AnalyticsServicePreboot, } from './src/contracts'; + +export type { + AnalyticsClient, + AnalyticsClientInitContext, + // Types for the registerShipper API + ShipperClassConstructor, + RegisterShipperOpts, + // Types for the optIn API + OptInConfig, + OptInConfigPerType, + ShipperName, + // Types for the registerContextProvider API + ContextProviderOpts, + ContextProviderName, + // Types for the registerEventType API + EventTypeOpts, + // Events + Event, + EventContext, + EventType, + TelemetryCounter, + TelemetryCounterType, + // Schema + RootSchema, + SchemaObject, + SchemaArray, + SchemaChildValue, + SchemaMeta, + SchemaValue, + SchemaMetaOptional, + PossibleSchemaTypes, + AllowedSchemaBooleanTypes, + AllowedSchemaNumberTypes, + AllowedSchemaStringTypes, + AllowedSchemaTypes, + // Shippers + IShipper, +} from '@kbn/ebt/client'; diff --git a/packages/core/analytics/core-analytics-server/src/contracts.ts b/packages/core/analytics/core-analytics-server/src/contracts.ts index 4879b988b1752..531c4ef6afd1f 100644 --- a/packages/core/analytics/core-analytics-server/src/contracts.ts +++ b/packages/core/analytics/core-analytics-server/src/contracts.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; /** * Exposes the public APIs of the AnalyticsClient during the preboot phase diff --git a/packages/core/analytics/core-analytics-server/tsconfig.json b/packages/core/analytics/core-analytics-server/tsconfig.json index 9c3a721a57e23..aa81d68980cd9 100644 --- a/packages/core/analytics/core-analytics-server/tsconfig.json +++ b/packages/core/analytics/core-analytics-server/tsconfig.json @@ -11,7 +11,7 @@ "**/*.ts" ], "kbn_references": [ - "@kbn/analytics-client" + "@kbn/ebt" ], "exclude": [ "target/**/*", diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_types.ts b/packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_types.ts index 7c4b08cd8647d..35e012fe2f625 100644 --- a/packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_types.ts +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { type RootSchema, type EventTypeOpts } from '@kbn/analytics-client'; +import { type RootSchema, type EventTypeOpts } from '@kbn/ebt/client'; export enum EventMetric { TOAST_DISMISSED = 'global_toast_list_toast_dismissed', diff --git a/packages/core/notifications/core-notifications-browser-internal/tsconfig.json b/packages/core/notifications/core-notifications-browser-internal/tsconfig.json index 0250d4b80488b..88855bd5bd4bb 100644 --- a/packages/core/notifications/core-notifications-browser-internal/tsconfig.json +++ b/packages/core/notifications/core-notifications-browser-internal/tsconfig.json @@ -31,7 +31,7 @@ "@kbn/react-kibana-context-render", "@kbn/core-analytics-browser", "@kbn/core-analytics-browser-mocks", - "@kbn/analytics-client", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/packages/core/status/core-status-server-internal/src/status_service.ts b/packages/core/status/core-status-server-internal/src/status_service.ts index 3947f04c61574..a24153342543c 100644 --- a/packages/core/status/core-status-server-internal/src/status_service.ts +++ b/packages/core/status/core-status-server-internal/src/status_service.ts @@ -18,7 +18,7 @@ import { import { map, distinctUntilChanged, shareReplay, takeUntil, debounceTime } from 'rxjs'; import { isDeepStrictEqual } from 'util'; -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/ebt/client'; import type { Logger, LogMeta } from '@kbn/logging'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { PluginName } from '@kbn/core-base-common'; diff --git a/packages/core/status/core-status-server-internal/tsconfig.json b/packages/core/status/core-status-server-internal/tsconfig.json index 0cc9f82b84794..42d4e92c57e0a 100644 --- a/packages/core/status/core-status-server-internal/tsconfig.json +++ b/packages/core/status/core-status-server-internal/tsconfig.json @@ -16,7 +16,6 @@ "@kbn/std", "@kbn/logging", "@kbn/i18n", - "@kbn/analytics-client", "@kbn/core-base-common", "@kbn/core-base-server-internal", "@kbn/core-http-server", @@ -42,6 +41,7 @@ "@kbn/core-analytics-server-mocks", "@kbn/core-logging-server-internal", "@kbn/core-logging-server-mocks", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-ebt-tools/src/performance_metric_events/helpers.test.ts b/packages/kbn-ebt-tools/src/performance_metric_events/helpers.test.ts index a6ad3970a6a97..de4271a474961 100644 --- a/packages/kbn-ebt-tools/src/performance_metric_events/helpers.test.ts +++ b/packages/kbn-ebt-tools/src/performance_metric_events/helpers.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { createAnalytics, type AnalyticsClient } from '@kbn/analytics-client'; +import { createAnalytics, type AnalyticsClient } from '@kbn/ebt/client'; import { loggerMock } from '@kbn/logging-mocks'; import { registerPerformanceMetricEventType, reportPerformanceMetricEvent } from './helpers'; import { METRIC_EVENT_SCHEMA } from './schema'; diff --git a/packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts b/packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts index f9aecd2bd7ec9..2763222c60d1f 100644 --- a/packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts +++ b/packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; import { type PerformanceMetricEvent, METRIC_EVENT_SCHEMA } from './schema'; const PERFORMANCE_METRIC_EVENT_TYPE = 'performance_metric'; diff --git a/packages/kbn-ebt-tools/src/performance_metric_events/schema.ts b/packages/kbn-ebt-tools/src/performance_metric_events/schema.ts index 15fdb4a1e9b33..b841b9b8d6f1d 100644 --- a/packages/kbn-ebt-tools/src/performance_metric_events/schema.ts +++ b/packages/kbn-ebt-tools/src/performance_metric_events/schema.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/ebt/client'; /** * Structure of the `metric` event diff --git a/packages/kbn-ebt-tools/tsconfig.json b/packages/kbn-ebt-tools/tsconfig.json index 7dd6d0703f073..881349b3f4d9b 100644 --- a/packages/kbn-ebt-tools/tsconfig.json +++ b/packages/kbn-ebt-tools/tsconfig.json @@ -5,6 +5,9 @@ "types": ["jest", "node"] }, "include": ["**/*.ts", "**/*.tsx"], - "kbn_references": ["@kbn/analytics-client", "@kbn/logging-mocks"], + "kbn_references": [ + "@kbn/logging-mocks", + "@kbn/ebt", + ], "exclude": ["target/**/*"] } diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 2260b78f90d9a..372eabdac9c95 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -96,20 +96,46 @@ export type { UiSettingsType, } from '@kbn/core-ui-settings-common'; -export type { AnalyticsServiceSetup, AnalyticsServiceStart } from '@kbn/core-analytics-browser'; export type { AnalyticsClient, - Event, - EventContext, - EventType, - EventTypeOpts, - IShipper, + AnalyticsClientInitContext, + AnalyticsServiceSetup, + AnalyticsServiceStart, + KbnAnalyticsWindowApi, + // Types for the registerShipper API ShipperClassConstructor, + RegisterShipperOpts, + // Types for the optIn API OptInConfig, + OptInConfigPerType, + ShipperName, + // Types for the registerContextProvider API ContextProviderOpts, + ContextProviderName, + // Types for the registerEventType API + EventTypeOpts, + // Events + Event, + EventContext, + EventType, TelemetryCounter, TelemetryCounterType, -} from '@kbn/analytics-client'; + // Schema + RootSchema, + SchemaObject, + SchemaArray, + SchemaChildValue, + SchemaMeta, + SchemaValue, + SchemaMetaOptional, + PossibleSchemaTypes, + AllowedSchemaBooleanTypes, + AllowedSchemaNumberTypes, + AllowedSchemaStringTypes, + AllowedSchemaTypes, + // Shippers + IShipper, +} from '@kbn/core-analytics-browser'; export { AppStatus } from '@kbn/core-application-browser'; export type { diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 901e0e3153651..1e89c9ed5b24e 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -482,21 +482,43 @@ export type { DocLinksServiceStart, DocLinksServiceSetup } from '@kbn/core-doc-l export type { AnalyticsClient, + AnalyticsClientInitContext, + AnalyticsServiceSetup, + AnalyticsServicePreboot, + AnalyticsServiceStart, + // Types for the registerShipper API + ShipperClassConstructor, + RegisterShipperOpts, + // Types for the optIn API + OptInConfig, + OptInConfigPerType, + ShipperName, + // Types for the registerContextProvider API + ContextProviderOpts, + ContextProviderName, + // Types for the registerEventType API + EventTypeOpts, + // Events Event, EventContext, EventType, - EventTypeOpts, - IShipper, - ContextProviderOpts, - OptInConfig, - ShipperClassConstructor, TelemetryCounter, TelemetryCounterType, -} from '@kbn/analytics-client'; -export type { - AnalyticsServiceSetup, - AnalyticsServicePreboot, - AnalyticsServiceStart, + // Schema + RootSchema, + SchemaObject, + SchemaArray, + SchemaChildValue, + SchemaMeta, + SchemaValue, + SchemaMetaOptional, + PossibleSchemaTypes, + AllowedSchemaBooleanTypes, + AllowedSchemaNumberTypes, + AllowedSchemaStringTypes, + AllowedSchemaTypes, + // Shippers + IShipper, } from '@kbn/core-analytics-server'; export type { RequestHandlerContext, diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json index 05ae89cb1be93..017ffa69c3107 100644 --- a/src/core/tsconfig.json +++ b/src/core/tsconfig.json @@ -124,7 +124,6 @@ "@kbn/core-deprecations-common", "@kbn/core-status-server", "@kbn/core-doc-links-server", - "@kbn/analytics-client", "@kbn/core-analytics-server", "@kbn/core-lifecycle-server", "@kbn/core-doc-links-browser", diff --git a/src/plugins/kibana_usage_collection/public/ebt_counters/register_ebt_counters.test.ts b/src/plugins/kibana_usage_collection/public/ebt_counters/register_ebt_counters.test.ts index a546f54f52261..9e2be1c709f0a 100644 --- a/src/plugins/kibana_usage_collection/public/ebt_counters/register_ebt_counters.test.ts +++ b/src/plugins/kibana_usage_collection/public/ebt_counters/register_ebt_counters.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { TelemetryCounter } from '@kbn/analytics-client'; +import type { TelemetryCounter } from '@kbn/core/public'; import { coreMock } from '@kbn/core/public/mocks'; import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/public/mocks'; import { registerEbtCounters } from './register_ebt_counters'; diff --git a/src/plugins/kibana_usage_collection/server/ebt_counters/register_ebt_counters.test.ts b/src/plugins/kibana_usage_collection/server/ebt_counters/register_ebt_counters.test.ts index c58a81dda10e6..a2ac2366c0b3e 100644 --- a/src/plugins/kibana_usage_collection/server/ebt_counters/register_ebt_counters.test.ts +++ b/src/plugins/kibana_usage_collection/server/ebt_counters/register_ebt_counters.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { TelemetryCounter } from '@kbn/analytics-client'; +import type { TelemetryCounter } from '@kbn/core/server'; import { coreMock } from '@kbn/core/server/mocks'; import { createUsageCollectionSetupMock } from '@kbn/usage-collection-plugin/server/mocks'; import { registerEbtCounters } from './register_ebt_counters'; diff --git a/src/plugins/kibana_usage_collection/tsconfig.json b/src/plugins/kibana_usage_collection/tsconfig.json index d56cb860cd463..2fb915d541052 100644 --- a/src/plugins/kibana_usage_collection/tsconfig.json +++ b/src/plugins/kibana_usage_collection/tsconfig.json @@ -13,7 +13,6 @@ "kbn_references": [ "@kbn/core", "@kbn/usage-collection-plugin", - "@kbn/analytics-client", "@kbn/i18n", "@kbn/logging", "@kbn/core-test-helpers-kbn-server", diff --git a/src/plugins/telemetry/public/plugin.test.ts b/src/plugins/telemetry/public/plugin.test.ts index 842e11f12cc68..f943f2cae86d1 100644 --- a/src/plugins/telemetry/public/plugin.test.ts +++ b/src/plugins/telemetry/public/plugin.test.ts @@ -7,7 +7,7 @@ */ import { of } from 'rxjs'; -import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; +import { ElasticV3BrowserShipper } from '@kbn/ebt/shippers/elastic_v3/browser'; import { coreMock } from '@kbn/core/public/mocks'; import { homePluginMock } from '@kbn/home-plugin/public/mocks'; import { screenshotModePluginMock } from '@kbn/screenshot-mode-plugin/public/mocks'; diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index 26a4f50af96ca..9b5a2c3af596a 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -22,7 +22,7 @@ import type { ScreenshotModePluginStart, } from '@kbn/screenshot-mode-plugin/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; -import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; +import { ElasticV3BrowserShipper } from '@kbn/ebt/shippers/elastic_v3/browser'; import { isSyntheticsMonitor } from '@kbn/analytics-collection-utils'; import { BehaviorSubject, map, switchMap, tap } from 'rxjs'; diff --git a/src/plugins/telemetry/server/plugin.test.ts b/src/plugins/telemetry/server/plugin.test.ts index 7d997bbc7c528..6410deb2daa59 100644 --- a/src/plugins/telemetry/server/plugin.test.ts +++ b/src/plugins/telemetry/server/plugin.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; +import { ElasticV3ServerShipper } from '@kbn/ebt/shippers/elastic_v3/server'; import { coreMock } from '@kbn/core/server/mocks'; import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/server/mocks'; import { telemetryCollectionManagerPluginMock } from '@kbn/telemetry-collection-manager-plugin/server/mocks'; diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index 394bfa18cb21e..be8f298218e0f 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -22,7 +22,7 @@ import { map, } from 'rxjs'; -import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; +import { ElasticV3ServerShipper } from '@kbn/ebt/shippers/elastic_v3/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { diff --git a/src/plugins/telemetry/tsconfig.json b/src/plugins/telemetry/tsconfig.json index 89d15d4f5a0a7..c6198c377832e 100644 --- a/src/plugins/telemetry/tsconfig.json +++ b/src/plugins/telemetry/tsconfig.json @@ -20,12 +20,10 @@ "@kbn/telemetry-collection-manager-plugin", "@kbn/usage-collection-plugin", "@kbn/security-plugin", - "@kbn/analytics-shippers-elastic-v3-browser", "@kbn/test-jest-helpers", "@kbn/shared-ux-utility", "@kbn/i18n", "@kbn/i18n-react", - "@kbn/analytics-shippers-elastic-v3-server", "@kbn/config-schema", "@kbn/utils", "@kbn/core-saved-objects-server", @@ -37,6 +35,7 @@ "@kbn/analytics-collection-utils", "@kbn/react-kibana-mount", "@kbn/core-node-server", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/src/plugins/usage_collection/server/collector/types.ts b/src/plugins/usage_collection/server/collector/types.ts index 50a04560e384b..9c1802348a113 100644 --- a/src/plugins/usage_collection/server/collector/types.ts +++ b/src/plugins/usage_collection/server/collector/types.ts @@ -8,7 +8,7 @@ import type { ElasticsearchClient, SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import type { PossibleSchemaTypes, SchemaMetaOptional } from '@kbn/analytics-client'; +import type { PossibleSchemaTypes, SchemaMetaOptional } from '@kbn/ebt/client'; export type { AllowedSchemaTypes, @@ -16,7 +16,7 @@ export type { AllowedSchemaBooleanTypes, AllowedSchemaNumberTypes, PossibleSchemaTypes, -} from '@kbn/analytics-client'; +} from '@kbn/ebt/client'; /** * Helper to find out whether to keep recursively looking or if we are on an end value diff --git a/src/plugins/usage_collection/tsconfig.json b/src/plugins/usage_collection/tsconfig.json index d7cf3f1e4c19f..e7c24d604be96 100644 --- a/src/plugins/usage_collection/tsconfig.json +++ b/src/plugins/usage_collection/tsconfig.json @@ -17,12 +17,12 @@ "@kbn/config-schema", "@kbn/screenshot-mode-plugin", "@kbn/std", - "@kbn/analytics-client", "@kbn/utility-types", "@kbn/i18n", "@kbn/core-http-server-mocks", "@kbn/analytics-collection-utils", "@kbn/logging", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/test/analytics/plugins/analytics_ftr_helpers/common/fetch_events.ts b/test/analytics/plugins/analytics_ftr_helpers/common/fetch_events.ts index 5a5eeba914b7b..9a2e235a0aa6a 100644 --- a/test/analytics/plugins/analytics_ftr_helpers/common/fetch_events.ts +++ b/test/analytics/plugins/analytics_ftr_helpers/common/fetch_events.ts @@ -18,7 +18,7 @@ import { toArray, } from 'rxjs'; import { get } from 'lodash'; -import type { Event } from '@kbn/analytics-client'; +import type { Event } from '@kbn/ebt/client'; import type { GetEventsOptions } from './types'; export async function fetchEvents( diff --git a/test/analytics/plugins/analytics_ftr_helpers/common/types.ts b/test/analytics/plugins/analytics_ftr_helpers/common/types.ts index 97e1faff823a4..25c3a8b738fe2 100644 --- a/test/analytics/plugins/analytics_ftr_helpers/common/types.ts +++ b/test/analytics/plugins/analytics_ftr_helpers/common/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { Event, EventType } from '@kbn/analytics-client'; +import type { Event, EventType } from '@kbn/ebt/client'; export type FiltersOptions = { [key in 'eq' | 'gte' | 'gt' | 'lte' | 'lt']?: unknown; diff --git a/test/analytics/plugins/analytics_ftr_helpers/public/custom_shipper.ts b/test/analytics/plugins/analytics_ftr_helpers/public/custom_shipper.ts index df876da5e9cce..c122c6310e04b 100644 --- a/test/analytics/plugins/analytics_ftr_helpers/public/custom_shipper.ts +++ b/test/analytics/plugins/analytics_ftr_helpers/public/custom_shipper.ts @@ -7,8 +7,7 @@ */ import { Subject } from 'rxjs'; -import type { AnalyticsClientInitContext } from '@kbn/analytics-client'; -import type { Event, IShipper } from '@kbn/core/public'; +import type { AnalyticsClientInitContext, Event, IShipper } from '@kbn/core/public'; export class CustomShipper implements IShipper { public static shipperName = 'FTR-helpers-shipper'; diff --git a/test/analytics/plugins/analytics_ftr_helpers/server/custom_shipper.ts b/test/analytics/plugins/analytics_ftr_helpers/server/custom_shipper.ts index c1ed593673f81..f15d03efe3d7d 100644 --- a/test/analytics/plugins/analytics_ftr_helpers/server/custom_shipper.ts +++ b/test/analytics/plugins/analytics_ftr_helpers/server/custom_shipper.ts @@ -7,8 +7,7 @@ */ import { Subject } from 'rxjs'; -import type { AnalyticsClientInitContext } from '@kbn/analytics-client'; -import type { IShipper, Event } from '@kbn/core/server'; +import type { AnalyticsClientInitContext, IShipper, Event } from '@kbn/core/server'; export class CustomShipper implements IShipper { public static shipperName = 'FTR-helpers-shipper'; diff --git a/test/analytics/plugins/analytics_ftr_helpers/tsconfig.json b/test/analytics/plugins/analytics_ftr_helpers/tsconfig.json index c6f087def9b01..352e95c717114 100644 --- a/test/analytics/plugins/analytics_ftr_helpers/tsconfig.json +++ b/test/analytics/plugins/analytics_ftr_helpers/tsconfig.json @@ -15,8 +15,8 @@ ], "kbn_references": [ "@kbn/core", - "@kbn/analytics-client", "@kbn/std", "@kbn/config-schema", + "@kbn/ebt", ] } diff --git a/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts b/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts index aa11e35249509..7ca8b42085025 100644 --- a/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts +++ b/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { Event } from '@kbn/analytics-client'; +import { Event } from '@kbn/core/server'; import { FtrProviderContext } from '../../../services'; export default function ({ getService }: FtrProviderContext) { diff --git a/test/tsconfig.json b/test/tsconfig.json index 5028acbc0d830..33a192fc996c6 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -61,7 +61,6 @@ "@kbn/core-application-browser", "@kbn/screenshot-mode-plugin", "@kbn/dev-utils", - "@kbn/analytics-client", "@kbn/utility-types", "@kbn/dev-proc-runner", "@kbn/enterprise-search-plugin", diff --git a/tsconfig.base.json b/tsconfig.base.json index dda059e9432ee..9c7e088b966d3 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -64,22 +64,12 @@ "@kbn/ambient-ui-types/*": ["packages/kbn-ambient-ui-types/*"], "@kbn/analytics": ["packages/kbn-analytics"], "@kbn/analytics/*": ["packages/kbn-analytics/*"], - "@kbn/analytics-client": ["packages/analytics/client"], - "@kbn/analytics-client/*": ["packages/analytics/client/*"], "@kbn/analytics-collection-utils": ["packages/analytics/utils/analytics_collection_utils"], "@kbn/analytics-collection-utils/*": ["packages/analytics/utils/analytics_collection_utils/*"], "@kbn/analytics-ftr-helpers-plugin": ["test/analytics/plugins/analytics_ftr_helpers"], "@kbn/analytics-ftr-helpers-plugin/*": ["test/analytics/plugins/analytics_ftr_helpers/*"], "@kbn/analytics-plugin-a-plugin": ["test/analytics/plugins/analytics_plugin_a"], "@kbn/analytics-plugin-a-plugin/*": ["test/analytics/plugins/analytics_plugin_a/*"], - "@kbn/analytics-shippers-elastic-v3-browser": ["packages/analytics/shippers/elastic_v3/browser"], - "@kbn/analytics-shippers-elastic-v3-browser/*": ["packages/analytics/shippers/elastic_v3/browser/*"], - "@kbn/analytics-shippers-elastic-v3-common": ["packages/analytics/shippers/elastic_v3/common"], - "@kbn/analytics-shippers-elastic-v3-common/*": ["packages/analytics/shippers/elastic_v3/common/*"], - "@kbn/analytics-shippers-elastic-v3-server": ["packages/analytics/shippers/elastic_v3/server"], - "@kbn/analytics-shippers-elastic-v3-server/*": ["packages/analytics/shippers/elastic_v3/server/*"], - "@kbn/analytics-shippers-fullstory": ["packages/analytics/shippers/fullstory"], - "@kbn/analytics-shippers-fullstory/*": ["packages/analytics/shippers/fullstory/*"], "@kbn/apm-config-loader": ["packages/kbn-apm-config-loader"], "@kbn/apm-config-loader/*": ["packages/kbn-apm-config-loader/*"], "@kbn/apm-data-access-plugin": ["x-pack/plugins/observability_solution/apm_data_access"], @@ -750,6 +740,8 @@ "@kbn/docs-utils/*": ["packages/kbn-docs-utils/*"], "@kbn/dom-drag-drop": ["packages/kbn-dom-drag-drop"], "@kbn/dom-drag-drop/*": ["packages/kbn-dom-drag-drop/*"], + "@kbn/ebt": ["packages/analytics/ebt"], + "@kbn/ebt/*": ["packages/analytics/ebt/*"], "@kbn/ebt-tools": ["packages/kbn-ebt-tools"], "@kbn/ebt-tools/*": ["packages/kbn-ebt-tools/*"], "@kbn/ecs-data-quality-dashboard": ["x-pack/packages/security-solution/ecs_data_quality_dashboard"], diff --git a/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts b/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts index e907a8bc024b7..204b940c45cd5 100644 --- a/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts +++ b/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; import { of } from 'rxjs'; import { parseDeploymentIdFromDeploymentUrl } from './parse_deployment_id_from_deployment_url'; diff --git a/x-pack/plugins/cloud/tsconfig.json b/x-pack/plugins/cloud/tsconfig.json index f5d0f3623fc78..ec6d5881a0531 100644 --- a/x-pack/plugins/cloud/tsconfig.json +++ b/x-pack/plugins/cloud/tsconfig.json @@ -13,10 +13,10 @@ "kbn_references": [ "@kbn/core", "@kbn/usage-collection-plugin", - "@kbn/analytics-client", "@kbn/config-schema", "@kbn/logging-mocks", "@kbn/logging", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts b/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts index a9af52c9a6b31..a3b7207eb3122 100755 --- a/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts +++ b/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts @@ -69,7 +69,7 @@ export class CloudFullStoryPlugin implements Plugin { } // Keep this import async so that we do not load any FullStory code into the browser when it is disabled. - const { FullStoryShipper } = await import('@kbn/analytics-shippers-fullstory'); + const { FullStoryShipper } = await import('@kbn/ebt/shippers/fullstory'); analytics.registerShipper(FullStoryShipper, { eventTypesAllowlist, fullStoryOrgId, diff --git a/x-pack/plugins/cloud_integrations/cloud_full_story/tsconfig.json b/x-pack/plugins/cloud_integrations/cloud_full_story/tsconfig.json index 47b6a5837a829..852ce8bb8af86 100644 --- a/x-pack/plugins/cloud_integrations/cloud_full_story/tsconfig.json +++ b/x-pack/plugins/cloud_integrations/cloud_full_story/tsconfig.json @@ -14,7 +14,7 @@ "@kbn/core", "@kbn/cloud-plugin", "@kbn/config-schema", - "@kbn/analytics-shippers-fullstory", + "@kbn/ebt", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts b/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts index ad25c6b2e976f..85859b2c232b7 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; +import type { EventTypeOpts } from '@kbn/core/server'; export const KNOWLEDGE_BASE_EXECUTION_SUCCESS_EVENT: EventTypeOpts<{ model: string; diff --git a/x-pack/plugins/elastic_assistant/tsconfig.json b/x-pack/plugins/elastic_assistant/tsconfig.json index d4ce180d8496d..dde693653c04c 100644 --- a/x-pack/plugins/elastic_assistant/tsconfig.json +++ b/x-pack/plugins/elastic_assistant/tsconfig.json @@ -13,7 +13,6 @@ "../../../typings/**/*" ], "kbn_references": [ - "@kbn/analytics-client", "@kbn/core", "@kbn/core-http-server", "@kbn/licensing-plugin", diff --git a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts index 912d0c0413c06..35138145a7141 100644 --- a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts +++ b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/server'; export const fleetAgentsSchema: RootSchema = { agents_per_version: { diff --git a/x-pack/plugins/fleet/tsconfig.json b/x-pack/plugins/fleet/tsconfig.json index 8bee11fed5d0e..7a8f58732902f 100644 --- a/x-pack/plugins/fleet/tsconfig.json +++ b/x-pack/plugins/fleet/tsconfig.json @@ -86,7 +86,6 @@ "@kbn/core-saved-objects-api-server-mocks", "@kbn/core-saved-objects-api-server", "@kbn/logging", - "@kbn/analytics-client", "@kbn/core-logging-server-mocks", "@kbn/ml-is-populated-object", "@kbn/utils", diff --git a/x-pack/plugins/global_search_bar/public/telemetry/event_types.ts b/x-pack/plugins/global_search_bar/public/telemetry/event_types.ts index bae58ca05b950..0b95e531d7f9c 100644 --- a/x-pack/plugins/global_search_bar/public/telemetry/event_types.ts +++ b/x-pack/plugins/global_search_bar/public/telemetry/event_types.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { RootSchema } from '@kbn/analytics-client'; -import { EventTypeOpts } from '@kbn/core/public'; +import { RootSchema, EventTypeOpts } from '@kbn/core/public'; import { EventMetric, FieldType } from '../types'; const fields: Record>> = { diff --git a/x-pack/plugins/global_search_bar/tsconfig.json b/x-pack/plugins/global_search_bar/tsconfig.json index 1e66c8225abea..f566b0d86eddc 100644 --- a/x-pack/plugins/global_search_bar/tsconfig.json +++ b/x-pack/plugins/global_search_bar/tsconfig.json @@ -14,7 +14,6 @@ "@kbn/i18n", "@kbn/saved-objects-tagging-oss-plugin", "@kbn/core-chrome-browser", - "@kbn/analytics-client", "@kbn/react-kibana-context-render", ], "exclude": [ diff --git a/x-pack/plugins/licensing/common/register_analytics_context_provider.ts b/x-pack/plugins/licensing/common/register_analytics_context_provider.ts index 60f3fbbb3e603..5defe217901b2 100644 --- a/x-pack/plugins/licensing/common/register_analytics_context_provider.ts +++ b/x-pack/plugins/licensing/common/register_analytics_context_provider.ts @@ -7,7 +7,7 @@ import type { Observable } from 'rxjs'; import { map } from 'rxjs'; -import type { AnalyticsClient } from '@kbn/analytics-client'; +import type { AnalyticsClient } from '@kbn/ebt/client'; import type { ILicense } from './types'; export function registerAnalyticsContextProvider( diff --git a/x-pack/plugins/licensing/tsconfig.json b/x-pack/plugins/licensing/tsconfig.json index f726ed7c09123..8eed250935b33 100644 --- a/x-pack/plugins/licensing/tsconfig.json +++ b/x-pack/plugins/licensing/tsconfig.json @@ -12,9 +12,9 @@ "@kbn/config-schema", "@kbn/std", "@kbn/i18n", - "@kbn/analytics-client", "@kbn/logging-mocks", - "@kbn/react-kibana-mount" + "@kbn/react-kibana-mount", + "@kbn/ebt" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/observability_solution/apm/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/apm/public/services/telemetry/types.ts index 11a8a6f225f27..5592974de2d40 100644 --- a/x-pack/plugins/observability_solution/apm/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/apm/public/services/telemetry/types.ts @@ -5,8 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; -import type { AnalyticsServiceSetup } from '@kbn/core/public'; +import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; export interface TelemetryServiceSetupParams { analytics: AnalyticsServiceSetup; diff --git a/x-pack/plugins/observability_solution/apm/tsconfig.json b/x-pack/plugins/observability_solution/apm/tsconfig.json index 981980f93b92e..c763acff6ea85 100644 --- a/x-pack/plugins/observability_solution/apm/tsconfig.json +++ b/x-pack/plugins/observability_solution/apm/tsconfig.json @@ -99,7 +99,6 @@ "@kbn/profiling-data-access-plugin", "@kbn/profiling-utils", "@kbn/core-analytics-server", - "@kbn/analytics-client", "@kbn/monaco", "@kbn/deeplinks-observability", "@kbn/custom-icons", diff --git a/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts index 16bdb5658f740..1ac068d5bb231 100644 --- a/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts @@ -5,8 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; -import type { AnalyticsServiceSetup } from '@kbn/core/public'; +import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; export interface TelemetryServiceSetupParams { analytics: AnalyticsServiceSetup; diff --git a/x-pack/plugins/observability_solution/infra/tsconfig.json b/x-pack/plugins/observability_solution/infra/tsconfig.json index cb98f8ab0859e..d1d1f0542da0a 100644 --- a/x-pack/plugins/observability_solution/infra/tsconfig.json +++ b/x-pack/plugins/observability_solution/infra/tsconfig.json @@ -56,7 +56,6 @@ "@kbn/charts-plugin", "@kbn/lens-plugin", "@kbn/core-analytics-server", - "@kbn/analytics-client", "@kbn/shared-ux-router", "@kbn/alerts-as-data-utils", "@kbn/cases-plugin", diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts index fa0c670fa2988..01df60e95a952 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; +import type { EventTypeOpts } from '@kbn/core/public'; import type { Message, Conversation } from '../../../common'; import type { Feedback } from '../../components/buttons/feedback_buttons'; import { ObservabilityAIAssistantTelemetryEventType } from '../telemetry_event_type'; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/common.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/common.ts index 3c4d4ee0c75e0..b01a8e05a4ea5 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/common.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/common.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { Message } from '../../../common'; export const messageSchema: RootSchema = { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts index 7f8a37cf95aee..67bd03f1fcd4f 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; +import type { EventTypeOpts } from '@kbn/core/public'; import type { Message } from '../../../common'; import type { Feedback } from '../../components/buttons/feedback_buttons'; import { ObservabilityAIAssistantTelemetryEventType } from '../telemetry_event_type'; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts index b7ce5f2dacb38..9c6f6d45110b1 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; +import type { EventTypeOpts } from '@kbn/core/public'; import type { Message } from '../../../common'; import { ObservabilityAIAssistantTelemetryEventType } from '../telemetry_event_type'; import { messageSchema } from './common'; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/analytics/recall_ranking.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/analytics/recall_ranking.ts index 8a6f6a88d8538..ab6201780038a 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/analytics/recall_ranking.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/analytics/recall_ranking.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RootSchema, EventTypeOpts } from '@kbn/analytics-client'; +import { RootSchema, EventTypeOpts } from '@kbn/core/public'; interface ScoredDocument { content: string; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/tsconfig.json b/x-pack/plugins/observability_solution/observability_ai_assistant/tsconfig.json index 0db746a4ab80c..aa26acbb6154a 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/tsconfig.json @@ -15,7 +15,6 @@ "kbn_references": [ "@kbn/i18n", "@kbn/core-analytics-browser", - "@kbn/analytics-client", "@kbn/logging", "@kbn/core", "@kbn/server-route-repository", diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/telemetry_events.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/telemetry_events.ts index 3d8b6ce58f3f3..8776d2fd44dbb 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/common/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/telemetry_events.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { type EventTypeOpts } from '@kbn/analytics-client'; +import { type EventTypeOpts } from '@kbn/ebt/client'; export const DATA_RECEIVED_TELEMETRY_EVENT: EventTypeOpts<{ rowCount: number; diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json b/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json index a3b20757c0096..446c237e257eb 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/tsconfig.json @@ -47,10 +47,10 @@ "@kbn/shared-ux-prompt-not-found", "@kbn/slo-plugin", "@kbn/es-query", - "@kbn/analytics-client", "@kbn/core-analytics-browser", "@kbn/react-hooks", "@kbn/data-quality-plugin", + "@kbn/ebt", ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/observability_solution/observability_onboarding/common/telemetry_events.ts b/x-pack/plugins/observability_solution/observability_onboarding/common/telemetry_events.ts index 24a4167d257c7..998c3e9cc9122 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/common/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/observability_onboarding/common/telemetry_events.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { type EventTypeOpts } from '@kbn/analytics-client'; +import { type EventTypeOpts } from '@kbn/ebt/client'; export const OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT: EventTypeOpts<{ flow?: string; diff --git a/x-pack/plugins/observability_solution/observability_onboarding/tsconfig.json b/x-pack/plugins/observability_solution/observability_onboarding/tsconfig.json index eb31601928b87..947a1230afd16 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability_onboarding/tsconfig.json @@ -36,9 +36,9 @@ "@kbn/shared-ux-link-redirect-app", "@kbn/cloud-experiments-plugin", "@kbn/home-sample-data-tab", - "@kbn/analytics-client", "@kbn/react-kibana-context-render", - "@kbn/react-kibana-context-theme" + "@kbn/react-kibana-context-theme", + "@kbn/ebt" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/reporting/server/usage/register_event_types.ts b/x-pack/plugins/reporting/server/usage/register_event_types.ts index bf34d33cf37c7..6347443eee8f7 100644 --- a/x-pack/plugins/reporting/server/usage/register_event_types.ts +++ b/x-pack/plugins/reporting/server/usage/register_event_types.ts @@ -5,9 +5,7 @@ * 2.0. */ -import { RootSchema } from '@kbn/analytics-client'; -import { EventTypeOpts } from '@kbn/core/public'; -import type { CoreSetup } from '@kbn/core/server'; +import type { CoreSetup, EventTypeOpts, RootSchema } from '@kbn/core/server'; import { EventType, FieldType } from '@kbn/reporting-server'; const fields: Record>> = { diff --git a/x-pack/plugins/reporting/tsconfig.json b/x-pack/plugins/reporting/tsconfig.json index e0f781d28f62c..b52c02a72bed1 100644 --- a/x-pack/plugins/reporting/tsconfig.json +++ b/x-pack/plugins/reporting/tsconfig.json @@ -47,7 +47,6 @@ "@kbn/reporting-mocks-server", "@kbn/core-http-request-handler-context-server", "@kbn/reporting-public", - "@kbn/analytics-client", "@kbn/reporting-csv-share-panel", "@kbn/react-kibana-context-render", "@kbn/react-kibana-mount", diff --git a/x-pack/plugins/search_playground/server/analytics/events.ts b/x-pack/plugins/search_playground/server/analytics/events.ts index 4330cb1a9e795..0db146a2f45a5 100644 --- a/x-pack/plugins/search_playground/server/analytics/events.ts +++ b/x-pack/plugins/search_playground/server/analytics/events.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { EventTypeOpts } from '@kbn/analytics-client'; +import { EventTypeOpts } from '@kbn/core/server'; export interface SendMessageEventData { connectorType: string; diff --git a/x-pack/plugins/search_playground/tsconfig.json b/x-pack/plugins/search_playground/tsconfig.json index c75c9213103bf..7e7217975cc85 100644 --- a/x-pack/plugins/search_playground/tsconfig.json +++ b/x-pack/plugins/search_playground/tsconfig.json @@ -39,7 +39,6 @@ "@kbn/core-logging-server-mocks", "@kbn/analytics", "@kbn/usage-collection-plugin", - "@kbn/analytics-client", "@kbn/console-plugin" ], "exclude": [ diff --git a/x-pack/plugins/security/server/analytics/analytics_service.ts b/x-pack/plugins/security/server/analytics/analytics_service.ts index 98d316d8a8d5f..b5bbbf0079cf9 100644 --- a/x-pack/plugins/security/server/analytics/analytics_service.ts +++ b/x-pack/plugins/security/server/analytics/analytics_service.ts @@ -5,8 +5,11 @@ * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; -import type { AnalyticsServiceSetup as CoreAnalyticsServiceSetup, Logger } from '@kbn/core/server'; +import type { + AnalyticsServiceSetup as CoreAnalyticsServiceSetup, + EventTypeOpts, + Logger, +} from '@kbn/core/server'; import type { CSPViolationReport, diff --git a/x-pack/plugins/security/tsconfig.json b/x-pack/plugins/security/tsconfig.json index f3ccbabffff97..a555c58c5804e 100644 --- a/x-pack/plugins/security/tsconfig.json +++ b/x-pack/plugins/security/tsconfig.json @@ -65,7 +65,6 @@ "@kbn/core-http-server", "@kbn/core-http-server-mocks", "@kbn/remote-clusters-plugin", - "@kbn/analytics-client", "@kbn/security-plugin-types-common", "@kbn/security-plugin-types-public", "@kbn/security-plugin-types-server", diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/ai_assistant/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/ai_assistant/types.ts index 87dbb38b4b5c7..54a9660d3b2d8 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/ai_assistant/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/ai_assistant/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { TelemetryEventTypes } from '../../constants'; export interface ReportAssistantInvokedParams { diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/alerts_grouping/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/alerts_grouping/types.ts index cc654e532f88d..d2b5e227ee66a 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/alerts_grouping/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/alerts_grouping/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { TelemetryEventTypes } from '../../constants'; export interface ReportAlertsGroupingChangedParams { diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts index e76813d280bc0..dc83083bd38e3 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { TelemetryEventTypes } from '../../constants'; export interface ReportAttackDiscoveriesGeneratedParams { diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/data_quality/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/data_quality/types.ts index 2b31e6cefea4f..9e1d012811e3b 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/data_quality/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/data_quality/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { TelemetryEventTypes } from '../../constants'; export type ReportDataQualityIndexCheckedParams = ReportDataQualityCheckAllCompletedParams & { diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/document_details/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/document_details/types.ts index a090686c91267..7a3ff374eae3c 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/document_details/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/document_details/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { TelemetryEventTypes } from '../../constants'; export interface ReportDetailsFlyoutOpenedParams { diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/entity_analytics/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/entity_analytics/types.ts index 9d38694324e55..d71c48004d756 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/entity_analytics/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/entity_analytics/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { RiskSeverity } from '../../../../../../common/search_strategy'; import type { TelemetryEventTypes } from '../../constants'; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/onboarding/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/onboarding/types.ts index 51ceefb49d5be..f6f52a6d675d2 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/onboarding/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/onboarding/types.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; +import type { RootSchema } from '@kbn/core/public'; import type { StepLinkId } from '../../../../components/landing_page/onboarding/step_links/types'; import type { TelemetryEventTypes } from '../../constants'; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts index e42c2cd8ab23c..3be54678c0ad8 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts @@ -5,8 +5,7 @@ * 2.0. */ -import type { RootSchema } from '@kbn/analytics-client'; -import type { AnalyticsServiceSetup } from '@kbn/core/public'; +import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; import type { AttackDiscoveryTelemetryEvent, ReportAttackDiscoveriesGeneratedParams, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx index 0a8fdcbaacd87..1edb154db295c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/query_tab_unified_components.test.tsx @@ -84,7 +84,7 @@ const useIsExperimentalFeatureEnabledMock = jest.fn((feature: keyof Experimental jest.mock('../../../../../common/lib/kibana'); // unified-field-list is reporting multiple analytics events -jest.mock(`@kbn/analytics-client`); +jest.mock(`@kbn/ebt/client`); const TestComponent = (props: Partial>) => { const testComponentDefaultProps: ComponentProps = { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx index bca35ae0af446..4cb56cdeba012 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/index.test.tsx @@ -75,8 +75,8 @@ const useIsExperimentalFeatureEnabledMock = jest.fn((feature: keyof Experimental jest.mock('../../../../common/lib/kibana'); -// unified-field-list is is reporiting multiple analytics events -jest.mock(`@kbn/analytics-client`); +// unified-field-list is reporting multiple analytics events +jest.mock(`@kbn/ebt/client`); const columnsToDisplay = [ ...defaultUdtHeaders, diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts b/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts index af165617bf37c..03552f02e39cf 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; +import type { EventTypeOpts } from '@kbn/core/server'; import type { AssetCriticalityCsvUploadResponse } from '../../../../common/api/entity_analytics'; export const RISK_SCORE_EXECUTION_SUCCESS_EVENT: EventTypeOpts<{ diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 610a76cd6f5ee..f1320dc3205be 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -149,7 +149,6 @@ "@kbn/grouping", "@kbn/securitysolution-data-table", "@kbn/core-analytics-server", - "@kbn/analytics-client", "@kbn/security-solution-side-nav", "@kbn/ml-anomaly-utils", "@kbn/discover-plugin", diff --git a/x-pack/plugins/security_solution_serverless/server/telemetry/event_based_telemetry.ts b/x-pack/plugins/security_solution_serverless/server/telemetry/event_based_telemetry.ts index 919338437643f..578b37f389cb3 100644 --- a/x-pack/plugins/security_solution_serverless/server/telemetry/event_based_telemetry.ts +++ b/x-pack/plugins/security_solution_serverless/server/telemetry/event_based_telemetry.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { EventTypeOpts } from '@kbn/analytics-client'; +import type { EventTypeOpts } from '@kbn/core/server'; export const NLP_CLEANUP_TASK_EVENT: EventTypeOpts<{ failedToDeleteCount: number; diff --git a/x-pack/plugins/security_solution_serverless/tsconfig.json b/x-pack/plugins/security_solution_serverless/tsconfig.json index 5cf1fcc8431a4..a1c6cefd396ca 100644 --- a/x-pack/plugins/security_solution_serverless/tsconfig.json +++ b/x-pack/plugins/security_solution_serverless/tsconfig.json @@ -44,6 +44,5 @@ "@kbn/management-cards-navigation", "@kbn/discover-plugin", "@kbn/logging", - "@kbn/analytics-client", ] } diff --git a/yarn.lock b/yarn.lock index 463d1d469c7b1..834ac4b058356 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3277,10 +3277,6 @@ version "0.0.0" uid "" -"@kbn/analytics-client@link:packages/analytics/client": - version "0.0.0" - uid "" - "@kbn/analytics-collection-utils@link:packages/analytics/utils/analytics_collection_utils": version "0.0.0" uid "" @@ -3293,22 +3289,6 @@ version "0.0.0" uid "" -"@kbn/analytics-shippers-elastic-v3-browser@link:packages/analytics/shippers/elastic_v3/browser": - version "0.0.0" - uid "" - -"@kbn/analytics-shippers-elastic-v3-common@link:packages/analytics/shippers/elastic_v3/common": - version "0.0.0" - uid "" - -"@kbn/analytics-shippers-elastic-v3-server@link:packages/analytics/shippers/elastic_v3/server": - version "0.0.0" - uid "" - -"@kbn/analytics-shippers-fullstory@link:packages/analytics/shippers/fullstory": - version "0.0.0" - uid "" - "@kbn/analytics@link:packages/kbn-analytics": version "0.0.0" uid "" @@ -4657,6 +4637,10 @@ version "0.0.0" uid "" +"@kbn/ebt@link:packages/analytics/ebt": + version "0.0.0" + uid "" + "@kbn/ecs-data-quality-dashboard-plugin@link:x-pack/plugins/ecs_data_quality_dashboard": version "0.0.0" uid "" From e06ee80f86f159b89db3dea40e1f3924cb2e7df9 Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Tue, 18 Jun 2024 06:38:42 -0600 Subject: [PATCH 046/127] [ES|QL] validate inline casting (#185904) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds basic validation for inline casting. To do this I had to create a new type of AST node and update the validation logic. I sort of snuck in a refactor of our column checking logic as well. It just kind of happened 🤷‍♂️ Check out the validation tests for some good cases: https://github.com/elastic/kibana/pull/185904/files#diff-89c4af0faedcf80d51cfb19ae397a5898c7293055b19284a94cb3f6a7cd4d071R1948 ### Not covered yet One thing this doesn't cover is that some casts only work for some types of data. For example `123::cartesian_point` won't work... the value has to be a string. This is because `123::cartesian_point` is actually syntactic sugar for `to_cartesianpoint(123)`. In https://github.com/elastic/elasticsearch/pull/109713 Nik is giving us a table of the casts to their functions so that we can derive this data and be a bit more accurate. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Stratoula Kalafateli Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__tests__/ast_parser.inlinecast.test.ts | 67 +++++ packages/kbn-esql-ast/src/ast_helpers.ts | 39 ++- packages/kbn-esql-ast/src/ast_walker.ts | 26 +- packages/kbn-esql-ast/src/types.ts | 25 +- .../kbn-esql-validation-autocomplete/index.ts | 5 +- .../scripts/generate_function_definitions.ts | 35 +-- .../src/autocomplete/autocomplete.test.ts | 4 +- .../src/autocomplete/autocomplete.ts | 23 +- .../src/definitions/options.ts | 5 +- .../src/definitions/types.ts | 2 +- .../src/shared/esql_to_kibana_type.ts | 44 ++++ .../src/shared/helpers.ts | 96 ++++--- .../esql_validation_meta_tests.json | 126 ++++++++++ .../src/validation/validation.test.ts | 63 +++++ .../src/validation/validation.ts | 235 +++++++++++------- 15 files changed, 611 insertions(+), 184 deletions(-) create mode 100644 packages/kbn-esql-ast/src/__tests__/ast_parser.inlinecast.test.ts create mode 100644 packages/kbn-esql-validation-autocomplete/src/shared/esql_to_kibana_type.ts diff --git a/packages/kbn-esql-ast/src/__tests__/ast_parser.inlinecast.test.ts b/packages/kbn-esql-ast/src/__tests__/ast_parser.inlinecast.test.ts new file mode 100644 index 0000000000000..3f45f55b549da --- /dev/null +++ b/packages/kbn-esql-ast/src/__tests__/ast_parser.inlinecast.test.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { getAstAndSyntaxErrors as parse } from '../ast_parser'; +import { ESQLFunction, ESQLInlineCast, ESQLSingleAstItem } from '../types'; + +describe('Inline cast (::)', () => { + describe('correctly formatted', () => { + it('can be a command argument', () => { + const text = 'FROM kibana_ecommerce_data | EVAL field::string'; + const { ast, errors } = parse(text); + + expect(errors.length).toBe(0); + expect(ast[1].args[0]).toEqual( + expect.objectContaining({ + castType: 'string', + name: 'inlineCast', + type: 'inlineCast', + value: expect.objectContaining({ + name: 'field', + type: 'column', + }), + }) + ); + }); + + it('can be a function argument', () => { + const text = 'FROM kibana_ecommerce_data | EVAL round(field::long)'; + const { ast, errors } = parse(text); + + expect(errors.length).toBe(0); + expect((ast[1].args[0] as ESQLFunction).args[0]).toEqual( + expect.objectContaining({ + castType: 'long', + name: 'inlineCast', + type: 'inlineCast', + value: expect.objectContaining({ + name: 'field', + type: 'column', + }), + }) + ); + }); + + it('can be nested', () => { + const text = 'FROM kibana_ecommerce_data | EVAL field::long::string::datetime'; + const { ast, errors } = parse(text); + + expect(errors.length).toBe(0); + let currentNode = ast[1].args[0]; + let depth = 0; + + while (depth < 3) { + expect((currentNode as ESQLSingleAstItem).type).toBe('inlineCast'); + currentNode = (currentNode as ESQLInlineCast).value; + depth++; + } + + expect((currentNode as ESQLSingleAstItem).name).toBe('field'); + }); + }); +}); diff --git a/packages/kbn-esql-ast/src/ast_helpers.ts b/packages/kbn-esql-ast/src/ast_helpers.ts index ae97040ecaaf1..69ea76c091146 100644 --- a/packages/kbn-esql-ast/src/ast_helpers.ts +++ b/packages/kbn-esql-ast/src/ast_helpers.ts @@ -14,6 +14,7 @@ import { type Token, type ParserRuleContext, type TerminalNode } from 'antlr4'; import type { ArithmeticUnaryContext, DecimalValueContext, + InlineCastContext, IntegerValueContext, QualifiedIntegerLiteralContext, } from './antlr/esql_parser'; @@ -32,6 +33,8 @@ import type { ESQLCommandOption, ESQLAstItem, ESQLCommandMode, + ESQLInlineCast, + ESQLUnknownItem, } from './types'; export function nonNullable(v: T): v is NonNullable { @@ -61,6 +64,17 @@ export function createCommand(name: string, ctx: ParserRuleContext): ESQLCommand }; } +export function createInlineCast(ctx: InlineCastContext): Omit { + return { + type: 'inlineCast', + name: 'inlineCast', + text: ctx.getText(), + castType: ctx.dataType().getText(), + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + export function createList(ctx: ParserRuleContext, values: ESQLLiteral[]): ESQLList { return { type: 'list', @@ -120,11 +134,20 @@ export function textExistsAndIsValid(text: string | undefined): text is string { export function createLiteral( type: ESQLLiteral['literalType'], - node: TerminalNode | undefined -): ESQLLiteral | undefined { + node: TerminalNode | null +): ESQLLiteral { if (!node) { - return; + return { + type: 'literal', + name: 'unknown', + text: 'unknown', + value: 'unknown', + literalType: type, + location: { min: 0, max: 0 }, + incomplete: false, + } as ESQLLiteral; } + const text = node.getText(); const partialLiteral: Omit = { @@ -347,3 +370,13 @@ export function createOption(name: string, ctx: ParserRuleContext): ESQLCommandO ), }; } + +export function createUnknownItem(ctx: ParserRuleContext): ESQLUnknownItem { + return { + type: 'unknown', + name: 'unknown', + text: ctx.getText(), + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} diff --git a/packages/kbn-esql-ast/src/ast_walker.ts b/packages/kbn-esql-ast/src/ast_walker.ts index 064b1b7d3126e..fc47227a0b0ed 100644 --- a/packages/kbn-esql-ast/src/ast_walker.ts +++ b/packages/kbn-esql-ast/src/ast_walker.ts @@ -57,6 +57,7 @@ import { type ValueExpressionContext, ValueExpressionDefaultContext, IndexIdentifierContext, + InlineCastContext, } from './antlr/esql_parser'; import { createSource, @@ -76,6 +77,8 @@ import { createPolicy, createSetting, textExistsAndIsValid, + createInlineCast, + createUnknownItem, } from './ast_helpers'; import { getPosition } from './ast_position_utils'; import type { @@ -84,6 +87,7 @@ import type { ESQLFunction, ESQLCommandOption, ESQLAstItem, + ESQLInlineCast, } from './types'; export function collectAllSourceIdentifiers(ctx: FromCommandContext): ESQLAstItem[] { @@ -292,7 +296,7 @@ function getBooleanValue(ctx: BooleanLiteralContext | BooleanValueContext) { return createLiteral('boolean', booleanTerminalNode!); } -function getConstant(ctx: ConstantContext | undefined): ESQLAstItem | undefined { +function getConstant(ctx: ConstantContext): ESQLAstItem { if (ctx instanceof NullLiteralContext) { return createLiteral('null', ctx.NULL()); } @@ -334,6 +338,8 @@ function getConstant(ctx: ConstantContext | undefined): ESQLAstItem | undefined } return createList(ctx, values); } + + return createUnknownItem(ctx); } export function visitRenameClauses(clausesCtx: RenameClauseContext[]): ESQLAstItem[] { @@ -355,9 +361,7 @@ export function visitRenameClauses(clausesCtx: RenameClauseContext[]): ESQLAstIt .filter(nonNullable); } -export function visitPrimaryExpression( - ctx: PrimaryExpressionContext -): ESQLAstItem | ESQLAstItem[] | undefined { +export function visitPrimaryExpression(ctx: PrimaryExpressionContext): ESQLAstItem | ESQLAstItem[] { if (ctx instanceof ConstantDefaultContext) { return getConstant(ctx.constant()); } @@ -385,6 +389,18 @@ export function visitPrimaryExpression( } return fn; } + if (ctx instanceof InlineCastContext) { + return collectInlineCast(ctx); + } + return createUnknownItem(ctx); +} + +function collectInlineCast(ctx: InlineCastContext): ESQLInlineCast { + const primaryExpression = visitPrimaryExpression(ctx.primaryExpression()); + return { + ...createInlineCast(ctx), + value: primaryExpression, + }; } export function collectLogicalExpression(ctx: BooleanExpressionContext) { @@ -512,7 +528,7 @@ export function visitOrderExpression(ctx: OrderExpressionContext[]) { } if (orderCtx.NULLS()) { expression.push(createLiteral('string', orderCtx.NULLS()!)!); - if (orderCtx._nullOrdering) { + if (orderCtx._nullOrdering && orderCtx._nullOrdering.text !== '') { const innerTerminalNode = orderCtx.getToken(esql_parser.FIRST, 0) || orderCtx.getToken(esql_parser.LAST, 0); const literal = createLiteral('string', innerTerminalNode); diff --git a/packages/kbn-esql-ast/src/types.ts b/packages/kbn-esql-ast/src/types.ts index 927ab619abfed..22a53d6368d9d 100644 --- a/packages/kbn-esql-ast/src/types.ts +++ b/packages/kbn-esql-ast/src/types.ts @@ -18,7 +18,9 @@ export type ESQLSingleAstItem = | ESQLTimeInterval | ESQLList | ESQLLiteral - | ESQLCommandMode; + | ESQLCommandMode + | ESQLInlineCast + | ESQLUnknownItem; export type ESQLAstItem = ESQLSingleAstItem | ESQLAstItem[]; @@ -59,6 +61,27 @@ export interface ESQLFunction extends ESQLAstBaseItem { args: ESQLAstItem[]; } +export interface ESQLInlineCast extends ESQLAstBaseItem { + type: 'inlineCast'; + value: ValueType; + castType: string; +} + +/** + * This node represents something the AST generator + * didn't recognize in the ANTLR parse tree. + * + * It can show up if the AST generator code is out of sync + * with the ANTLR grammar or if there is some idiosyncrasy + * or bug in the parse tree. + * + * These nodes can be ignored for the purpose of validation + * and autocomplete, but they may be helpful in detecting bugs. + */ +export interface ESQLUnknownItem extends ESQLAstBaseItem { + type: 'unknown'; +} + export interface ESQLTimeInterval extends ESQLAstBaseItem { type: 'timeInterval'; unit: string; diff --git a/packages/kbn-esql-validation-autocomplete/index.ts b/packages/kbn-esql-validation-autocomplete/index.ts index d4c4420ffeca4..31bd8c16b76fb 100644 --- a/packages/kbn-esql-validation-autocomplete/index.ts +++ b/packages/kbn-esql-validation-autocomplete/index.ts @@ -49,11 +49,10 @@ export { getCommandDefinition, getAllCommands, getCommandOption, - getColumnHit, - columnExists, + lookupColumn, shouldBeQuotedText, printFunctionSignature, - isEqualType, + checkFunctionArgMatchesDefinition as isEqualType, isSourceItem, isSettingItem, isFunctionItem, diff --git a/packages/kbn-esql-validation-autocomplete/scripts/generate_function_definitions.ts b/packages/kbn-esql-validation-autocomplete/scripts/generate_function_definitions.ts index 15333c62300fa..ad9966defd9cb 100644 --- a/packages/kbn-esql-validation-autocomplete/scripts/generate_function_definitions.ts +++ b/packages/kbn-esql-validation-autocomplete/scripts/generate_function_definitions.ts @@ -12,6 +12,7 @@ import { join } from 'path'; import _ from 'lodash'; import type { RecursivePartial } from '@kbn/utility-types'; import { FunctionDefinition } from '../src/definitions/types'; +import { esqlToKibanaType } from '../src/shared/esql_to_kibana_type'; const aliasTable: Record = { to_version: ['to_ver'], @@ -56,36 +57,6 @@ const extraFunctions: FunctionDefinition[] = [ }, ]; -const elasticsearchToKibanaType = (elasticsearchType: string) => { - if ( - [ - 'double', - 'unsigned_long', - 'long', - 'integer', - 'counter_integer', - 'counter_long', - 'counter_double', - ].includes(elasticsearchType) - ) { - return 'number'; - } - - if (['text', 'keyword'].includes(elasticsearchType)) { - return 'string'; - } - - if (['datetime', 'time_duration'].includes(elasticsearchType)) { - return 'date'; - } - - if (elasticsearchType === 'date_period') { - return 'time_literal'; // TODO - consider aligning with Elasticsearch - } - - return elasticsearchType; -}; - const validateLogFunctions = `(fnDef: ESQLFunction) => { const messages = []; // do not really care here about the base and field @@ -237,10 +208,10 @@ function getFunctionDefinition(ESFunctionDefinition: Record): Funct ...signature, params: signature.params.map((param: any) => ({ ...param, - type: elasticsearchToKibanaType(param.type), + type: esqlToKibanaType(param.type), description: undefined, })), - returnType: elasticsearchToKibanaType(signature.returnType), + returnType: esqlToKibanaType(signature.returnType), variadic: undefined, // we don't support variadic property minParams: signature.variadic ? signature.params.filter((param: any) => !param.optional).length diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts index 528e5f338b53e..828511762a5f4 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts @@ -16,7 +16,7 @@ import { getUnitDuration, TRIGGER_SUGGESTION_COMMAND } from './factories'; import { camelCase, partition } from 'lodash'; import { getAstAndSyntaxErrors } from '@kbn/esql-ast'; import { groupingFunctionDefinitions } from '../definitions/grouping'; -import { FunctionArgSignature } from '../definitions/types'; +import { FunctionParameter } from '../definitions/types'; import { getParamAtPosition } from './helper'; import { nonNullable } from '../shared/helpers'; import { METADATA_FIELDS } from '../shared/constants'; @@ -1182,7 +1182,7 @@ describe('autocomplete', () => { (p) => p.constantOnly || /_literal/.test(p.type) ); - const getTypesFromParamDefs = (paramDefs: FunctionArgSignature[]) => + const getTypesFromParamDefs = (paramDefs: FunctionParameter[]) => Array.from(new Set(paramDefs.map((p) => p.type))); const suggestedConstants = param.literalSuggestions || param.literalOptions; diff --git a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts index ba2f180fb51f6..727335fe6d961 100644 --- a/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts +++ b/packages/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts @@ -18,8 +18,7 @@ import type { import { partition } from 'lodash'; import type { EditorContext, SuggestionRawDefinition } from './types'; import { - columnExists, - getColumnHit, + lookupColumn, getCommandDefinition, getCommandOption, getFunctionDefinition, @@ -42,6 +41,7 @@ import { getAllFunctions, isSingleItem, nonNullable, + getColumnExists, } from '../shared/helpers'; import { collectVariables, excludeVariablesFromCurrentCommand } from '../shared/variables'; import type { ESQLPolicy, ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; @@ -87,7 +87,7 @@ import { getSourcesFromCommands, isAggFunctionUsedAlready, } from './helper'; -import { FunctionArgSignature } from '../definitions/types'; +import { FunctionParameter } from '../definitions/types'; type GetSourceFn = () => Promise; type GetDataSourceFn = (sourceName: string) => Promise< @@ -345,7 +345,9 @@ function workoutBuiltinOptions( references: Pick ): { skipAssign: boolean } { // skip assign operator if it's a function or an existing field to avoid promoting shadowing - return { skipAssign: Boolean(!isColumnItem(nodeArg) || getColumnHit(nodeArg.name, references)) }; + return { + skipAssign: Boolean(!isColumnItem(nodeArg) || lookupColumn(nodeArg, references)), + }; } function areCurrentArgsValid( @@ -412,7 +414,7 @@ function extractFinalTypeFromArg( return arg.literalType; } if (isColumnItem(arg)) { - const hit = getColumnHit(arg.name, references); + const hit = lookupColumn(arg, references); if (hit) { return hit.type; } @@ -1166,10 +1168,10 @@ async function getFunctionArgsSuggestions( const isUnknownColumn = arg && isColumnItem(arg) && - !columnExists(arg, { + !getColumnExists(arg, { fields: fieldsMap, variables: variablesExcludingCurrentCommandOnes, - }).hit; + }); if (noArgDefined || isUnknownColumn) { // ... | EVAL fn( ) // ... | EVAL fn( field, ) @@ -1243,7 +1245,7 @@ async function getFunctionArgsSuggestions( (paramDef) => paramDef.constantOnly || /_literal$/.test(paramDef.type) ); - const getTypesFromParamDefs = (paramDefs: FunctionArgSignature[]) => { + const getTypesFromParamDefs = (paramDefs: FunctionParameter[]) => { return Array.from(new Set(paramDefs.map(({ type }) => type))); }; @@ -1517,7 +1519,10 @@ async function getOptionArgsSuggestions( } if (command.name === 'dissect') { - if (option.args.length < 1 && optionDef) { + if ( + option.args.filter((arg) => !(isSingleItem(arg) && arg.type === 'unknown')).length < 1 && + optionDef + ) { suggestions.push(colonCompleteItem, semiColonCompleteItem); } } diff --git a/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts b/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts index 8e30a43db2c8f..13e3ea66ef106 100644 --- a/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts +++ b/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { ESQLCommandOption, ESQLMessage } from '@kbn/esql-ast'; -import { isLiteralItem, isColumnItem } from '../shared/helpers'; +import { isLiteralItem, isColumnItem, isInlineCastItem } from '../shared/helpers'; import { getMessageFromId } from '../validation/errors'; import type { CommandOptionsDefinition } from './types'; @@ -130,7 +130,8 @@ export const appendSeparatorOption: CommandOptionsDefinition = { !Array.isArray(firstArg) && (!isLiteralItem(firstArg) || firstArg.literalType !== 'string') ) { - const value = 'value' in firstArg ? firstArg.value : firstArg.name; + const value = + 'value' in firstArg && !isInlineCastItem(firstArg) ? firstArg.value : firstArg.name; messages.push( getMessageFromId({ messageId: 'wrongDissectOptionArgumentType', diff --git a/packages/kbn-esql-validation-autocomplete/src/definitions/types.ts b/packages/kbn-esql-validation-autocomplete/src/definitions/types.ts index dbfbf08cca08a..05adb6eed5836 100644 --- a/packages/kbn-esql-validation-autocomplete/src/definitions/types.ts +++ b/packages/kbn-esql-validation-autocomplete/src/definitions/types.ts @@ -158,4 +158,4 @@ export type SignatureType = | CommandOptionsDefinition['signature']; export type SignatureArgType = SignatureType['params'][number]; -export type FunctionArgSignature = FunctionDefinition['signatures'][number]['params'][number]; +export type FunctionParameter = FunctionDefinition['signatures'][number]['params'][number]; diff --git a/packages/kbn-esql-validation-autocomplete/src/shared/esql_to_kibana_type.ts b/packages/kbn-esql-validation-autocomplete/src/shared/esql_to_kibana_type.ts new file mode 100644 index 0000000000000..f13052288f29f --- /dev/null +++ b/packages/kbn-esql-validation-autocomplete/src/shared/esql_to_kibana_type.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +const ESQL_NUMBER_TYPES = [ + 'double', + 'unsigned_long', + 'long', + 'integer', + 'int', + 'counter_integer', + 'counter_long', + 'counter_double', +]; + +const ESQL_TEXT_TYPES = ['text', 'keyword', 'string']; + +export const esqlToKibanaType = (elasticsearchType: string) => { + if (ESQL_NUMBER_TYPES.includes(elasticsearchType)) { + return 'number'; + } + + if (ESQL_TEXT_TYPES.includes(elasticsearchType)) { + return 'string'; + } + + if (['datetime', 'time_duration'].includes(elasticsearchType)) { + return 'date'; + } + + if (elasticsearchType === 'bool') { + return 'boolean'; + } + + if (elasticsearchType === 'date_period') { + return 'time_literal'; // TODO - consider aligning with Elasticsearch + } + + return elasticsearchType; +}; diff --git a/packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts b/packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts index 348a9b45e5d12..201b7bf045d0f 100644 --- a/packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts +++ b/packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts @@ -17,6 +17,7 @@ import type { ESQLSource, ESQLTimeInterval, } from '@kbn/esql-ast'; +import { ESQLInlineCast } from '@kbn/esql-ast/src/types'; import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; import { builtinFunctions } from '../definitions/builtin'; import { commandDefinitions } from '../definitions/commands'; @@ -35,14 +36,14 @@ import { import type { CommandDefinition, CommandOptionsDefinition, - FunctionArgSignature, + FunctionParameter, FunctionDefinition, FunctionParameterType, FunctionReturnType, - SignatureArgType, } from '../definitions/types'; import type { ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; import { removeMarkerArgFromArgsList } from './context'; +import { esqlToKibanaType } from './esql_to_kibana_type'; import type { ReasonTypes } from './types'; export function nonNullable(v: T): v is NonNullable { @@ -76,6 +77,10 @@ export function isLiteralItem(arg: ESQLAstItem): arg is ESQLLiteral { return isSingleItem(arg) && arg.type === 'literal'; } +export function isInlineCastItem(arg: ESQLAstItem): arg is ESQLInlineCast { + return isSingleItem(arg) && arg.type === 'inlineCast'; +} + export function isTimeIntervalItem(arg: ESQLAstItem): arg is ESQLTimeInterval { return isSingleItem(arg) && arg.type === 'timeInterval'; } @@ -235,11 +240,14 @@ function compareLiteralType(argType: string, item: ESQLLiteral) { return ['string', 'date'].includes(argType); } -export function getColumnHit( - columnName: string, - { fields, variables }: Pick, - position?: number +/** + * This function returns the variable or field matching a column + */ +export function lookupColumn( + column: ESQLColumn, + { fields, variables }: Pick ): ESQLRealField | ESQLVariable | undefined { + const columnName = getQuotedColumnName(column); return fields.get(columnName) || variables.get(columnName)?.[0]; } @@ -350,7 +358,7 @@ export function getAllArrayTypes( types.push(subArg.literalType); } if (subArg.type === 'column') { - const hit = getColumnHit(subArg.name, references); + const hit = lookupColumn(subArg, references); types.push(hit?.type || 'unsupported'); } if (subArg.type === 'timeInterval') { @@ -377,7 +385,7 @@ export function inKnownTimeInterval(item: ESQLTimeInterval): boolean { * * TODO - Consider merging with isEqualType to create a unified arg validation function */ -export function isValidLiteralOption(arg: ESQLLiteral, argDef: FunctionArgSignature) { +export function isValidLiteralOption(arg: ESQLLiteral, argDef: FunctionParameter) { return ( arg.literalType === 'string' && argDef.literalOptions && @@ -388,17 +396,16 @@ export function isValidLiteralOption(arg: ESQLLiteral, argDef: FunctionArgSignat } /** - * Checks if an AST argument is of the correct type + * Checks if an AST function argument is of the correct type * given the definition. */ -export function isEqualType( +export function checkFunctionArgMatchesDefinition( arg: ESQLSingleAstItem, - argDef: SignatureArgType, + parameterDefinition: FunctionParameter, references: ReferenceMaps, - parentCommand?: string, - nameHit?: string + parentCommand?: string ) { - const argType = 'innerType' in argDef && argDef.innerType ? argDef.innerType : argDef.type; + const argType = parameterDefinition.type; if (argType === 'any') { return true; } @@ -417,11 +424,7 @@ export function isEqualType( return argType === 'time_literal' && inKnownTimeInterval(arg); } if (arg.type === 'column') { - if (argType === 'column') { - // anything goes, so avoid any effort here - return true; - } - const hit = getColumnHit(nameHit ?? arg.name, references); + const hit = lookupColumn(arg, references); const validHit = hit; if (!validHit) { return false; @@ -430,6 +433,10 @@ export function isEqualType( // if final type is of type any make it pass for now return wrappedTypes.some((ct) => ['any', 'null'].includes(ct) || argType === ct); } + if (arg.type === 'inlineCast') { + // TODO - remove with https://github.com/elastic/kibana/issues/174710 + return argType === esqlToKibanaType(arg.castType); + } } function fuzzySearch(fuzzyName: string, resources: IterableIterator) { @@ -499,25 +506,48 @@ export function hasCCSSource(name: string) { return name.includes(':'); } -export function columnExists( +/** + * This will return the name without any quotes. + * + * E.g. "`bytes`" will become "bytes" + * + * @param column + * @returns + */ +export const getUnquotedColumnName = (column: ESQLColumn) => column.name; + +/** + * This returns the name with any quotes that were present. + * + * E.g. "`bytes`" will be "`bytes`" + * + * @param column + * @returns + */ +export const getQuotedColumnName = (column: ESQLColumn) => + column.quoted ? column.text : column.name; + +/** + * TODO - consider calling lookupColumn under the hood of this function. Seems like they should really do the same thing. + */ +export function getColumnExists( column: ESQLColumn, { fields, variables }: Pick ) { - if (fields.has(column.name) || variables.has(column.name)) { - return { hit: true, nameHit: column.name }; - } - if (column.quoted) { - const originalName = column.text; - if (variables.has(originalName)) { - return { hit: true, nameHit: originalName }; + const namesToCheck = [getUnquotedColumnName(column), getQuotedColumnName(column)]; + + for (const name of namesToCheck) { + if (fields.has(name) || variables.has(name)) { + return true; + } + + // TODO — I don't see this fuzzy searching in lookupColumn... should it be there? + if (Boolean(fuzzySearch(name, fields.keys()) || fuzzySearch(name, variables.keys()))) { + return true; } } - if ( - Boolean(fuzzySearch(column.name, fields.keys()) || fuzzySearch(column.name, variables.keys())) - ) { - return { hit: true, nameHit: column.name }; - } - return { hit: false }; + + return false; } export function sourceExists(index: string, sources: Set) { diff --git a/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json b/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json index 0fc1b047700a2..ba80daea19780 100644 --- a/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json +++ b/packages/kbn-esql-validation-autocomplete/src/validation/esql_validation_meta_tests.json @@ -8943,6 +8943,132 @@ "error": [], "warning": [] }, + { + "query": "from a_index | eval 1::string", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval 1::foo", + "error": [ + "Invalid type [foo] for casting" + ], + "warning": [] + }, + { + "query": "from a_index | eval 1::string::long::double", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval trim(\"23\"::double)", + "error": [ + "Argument of [trim] must be [string], found value [\"23\"::double] type [double]" + ], + "warning": [] + }, + { + "query": "from a_index | eval trim(23::string)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval 1 + \"2\"::long", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval 1 + \"2\"", + "error": [ + "Argument of [+] must be [number], found value [\"2\"] type [string]" + ], + "warning": [] + }, + { + "query": "from a_index | eval trim(to_double(\"23\")::string::double::long::string::double)", + "error": [ + "Argument of [trim] must be [string], found value [to_double(\"23\")::string::double::long::string::double] type [double]" + ], + "warning": [] + }, + { + "query": "from a_index | eval CEIL(23::long)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval CEIL(23::unsigned_long)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval CEIL(23::int)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval CEIL(23::integer)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval CEIL(23::double)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval TRIM(23::string)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval TRIM(23::text)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval TRIM(23::keyword)", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval true AND \"false\"::boolean", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval true AND \"false\"::bool", + "error": [], + "warning": [] + }, + { + "query": "from a_index | eval true AND \"false\"", + "error": [ + "Argument of [and] must be [boolean], found value [\"false\"] type [string]" + ], + "warning": [] + }, + { + "query": "from a_index | eval to_lower(trim(numberField)::string)", + "error": [ + "Argument of [trim] must be [string], found value [numberField] type [number]" + ], + "warning": [] + }, + { + "query": "from a_index | eval to_upper(trim(numberField)::string::string::string::string)", + "error": [ + "Argument of [trim] must be [string], found value [numberField] type [number]" + ], + "warning": [] + }, + { + "query": "from a_index | eval to_lower(to_upper(trim(numberField)::string)::string)", + "error": [ + "Argument of [trim] must be [string], found value [numberField] type [number]" + ], + "warning": [] + }, { "query": "row var = date_diff(\"month\", \"2023-12-02T11:00:00.000Z\", \"2023-12-02T11:00:00.000Z\")", "error": [], diff --git a/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts b/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts index 939cd5507ae27..edbe2e839ee25 100644 --- a/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts +++ b/packages/kbn-esql-validation-autocomplete/src/validation/validation.test.ts @@ -1945,6 +1945,69 @@ describe('validation logic', () => { }); }); + describe('inline casting', () => { + // accepts casting + testErrorsAndWarnings('from a_index | eval 1::string', []); + + // errors if the cast type is invalid + // testErrorsAndWarnings('from a_index | eval 1::foo', ['Invalid type [foo] for casting']); + + // accepts casting with multiple types + testErrorsAndWarnings('from a_index | eval 1::string::long::double', []); + + // takes into account casting in function arguments + testErrorsAndWarnings('from a_index | eval trim("23"::double)', [ + 'Argument of [trim] must be [string], found value ["23"::double] type [double]', + ]); + testErrorsAndWarnings('from a_index | eval trim(23::string)', []); + testErrorsAndWarnings('from a_index | eval 1 + "2"::long', []); + testErrorsAndWarnings('from a_index | eval 1 + "2"', [ + // just a counter-case to make sure the previous test is meaningful + 'Argument of [+] must be [number], found value ["2"] type [string]', + ]); + testErrorsAndWarnings( + 'from a_index | eval trim(to_double("23")::string::double::long::string::double)', + [ + 'Argument of [trim] must be [string], found value [to_double("23")::string::double::long::string::double] type [double]', + ] + ); + + // accepts elasticsearch subtypes and type aliases like int and keyword + // (once https://github.com/elastic/kibana/issues/174710 is done this won't be a special case anymore) + testErrorsAndWarnings('from a_index | eval CEIL(23::long)', []); + testErrorsAndWarnings('from a_index | eval CEIL(23::unsigned_long)', []); + testErrorsAndWarnings('from a_index | eval CEIL(23::int)', []); + testErrorsAndWarnings('from a_index | eval CEIL(23::integer)', []); + testErrorsAndWarnings('from a_index | eval CEIL(23::double)', []); + + testErrorsAndWarnings('from a_index | eval TRIM(23::string)', []); + testErrorsAndWarnings('from a_index | eval TRIM(23::text)', []); + testErrorsAndWarnings('from a_index | eval TRIM(23::keyword)', []); + + testErrorsAndWarnings('from a_index | eval true AND "false"::boolean', []); + testErrorsAndWarnings('from a_index | eval true AND "false"::bool', []); + testErrorsAndWarnings('from a_index | eval true AND "false"', [ + // just a counter-case to make sure the previous tests are meaningful + 'Argument of [and] must be [boolean], found value ["false"] type [string]', + ]); + + // enforces strings for cartesian_point conversion + // testErrorsAndWarnings('from a_index | eval 23::cartesian_point', ['wrong type!']); + + // still validates nested functions when they are casted + testErrorsAndWarnings('from a_index | eval to_lower(trim(numberField)::string)', [ + 'Argument of [trim] must be [string], found value [numberField] type [number]', + ]); + testErrorsAndWarnings( + 'from a_index | eval to_upper(trim(numberField)::string::string::string::string)', + ['Argument of [trim] must be [string], found value [numberField] type [number]'] + ); + testErrorsAndWarnings( + 'from a_index | eval to_lower(to_upper(trim(numberField)::string)::string)', + ['Argument of [trim] must be [string], found value [numberField] type [number]'] + ); + }); + describe(FUNCTION_DESCRIBE_BLOCK_NAME, () => { describe('date_diff', () => { testErrorsAndWarnings( diff --git a/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts b/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts index 0b44783daef0e..438d1fd826d00 100644 --- a/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts +++ b/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts @@ -22,19 +22,18 @@ import type { import { CommandModeDefinition, CommandOptionsDefinition, - FunctionArgSignature, + FunctionParameter, FunctionDefinition, - SignatureArgType, } from '../definitions/types'; import { areFieldAndVariableTypesCompatible, extractSingularType, - getColumnHit, + lookupColumn, getCommandDefinition, getFunctionDefinition, isArrayType, isColumnItem, - isEqualType, + checkFunctionArgMatchesDefinition, isFunctionItem, isLiteralItem, isOptionItem, @@ -44,16 +43,18 @@ import { inKnownTimeInterval, printFunctionSignature, sourceExists, - columnExists, + getColumnExists, hasWildcard, hasCCSSource, isSettingItem, isAssignment, isVariable, isValidLiteralOption, + getQuotedColumnName, + isInlineCastItem, } from '../shared/helpers'; import { collectVariables } from '../shared/variables'; -import { getMessageFromId, getUnknownTypeLabel } from './errors'; +import { getMessageFromId } from './errors'; import type { ErrorTypes, ESQLRealField, @@ -77,7 +78,7 @@ import { METADATA_FIELDS } from '../shared/constants'; function validateFunctionLiteralArg( astFunction: ESQLFunction, actualArg: ESQLAstItem, - argDef: FunctionArgSignature, + argDef: FunctionParameter, references: ReferenceMaps, parentCommand: string ) { @@ -101,7 +102,7 @@ function validateFunctionLiteralArg( ); } - if (!isEqualType(actualArg, argDef, references, parentCommand)) { + if (!checkFunctionArgMatchesDefinition(actualArg, argDef, references, parentCommand)) { messages.push( getMessageFromId({ messageId: 'wrongArgumentType', @@ -129,7 +130,7 @@ function validateFunctionLiteralArg( }) ); } else { - if (!isEqualType(actualArg, argDef, references, parentCommand)) { + if (!checkFunctionArgMatchesDefinition(actualArg, argDef, references, parentCommand)) { messages.push( getMessageFromId({ messageId: 'wrongArgumentType', @@ -148,10 +149,39 @@ function validateFunctionLiteralArg( return messages; } +function validateInlineCastArg( + astFunction: ESQLFunction, + arg: ESQLAstItem, + parameterDefinition: FunctionParameter, + references: ReferenceMaps, + parentCommand: string +) { + if (!isInlineCastItem(arg)) { + return []; + } + + if (!checkFunctionArgMatchesDefinition(arg, parameterDefinition, references, parentCommand)) { + return [ + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: parameterDefinition.type, + value: arg.text, + givenType: arg.castType, + }, + locations: arg.location, + }), + ]; + } + + return []; +} + function validateNestedFunctionArg( astFunction: ESQLFunction, actualArg: ESQLAstItem, - argDef: SignatureArgType, + parameterDefinition: FunctionParameter, references: ReferenceMaps, parentCommand: string ) { @@ -165,7 +195,11 @@ function validateNestedFunctionArg( const argFn = getFunctionDefinition(actualArg.name)!; const fnDef = getFunctionDefinition(astFunction.name)!; // no nestying criteria should be enforced only for same type function - if ('noNestingFunctions' in argDef && argDef.noNestingFunctions && fnDef.type === argFn.type) { + if ( + 'noNestingFunctions' in parameterDefinition && + parameterDefinition.noNestingFunctions && + fnDef.type === argFn.type + ) { messages.push( getMessageFromId({ messageId: 'noNestedArgumentSupport', @@ -174,13 +208,15 @@ function validateNestedFunctionArg( }) ); } - if (!isEqualType(actualArg, argDef, references, parentCommand)) { + if ( + !checkFunctionArgMatchesDefinition(actualArg, parameterDefinition, references, parentCommand) + ) { messages.push( getMessageFromId({ messageId: 'wrongArgumentType', values: { name: astFunction.name, - argType: argDef.type, + argType: parameterDefinition.type, value: printFunctionSignature(actualArg) || actualArg.name, givenType: argFn.signatures[0].returnType, }, @@ -195,85 +231,82 @@ function validateNestedFunctionArg( function validateFunctionColumnArg( astFunction: ESQLFunction, actualArg: ESQLAstItem, - argDef: SignatureArgType, + parameterDefinition: FunctionParameter, references: ReferenceMaps, parentCommand: string ) { const messages: ESQLMessage[] = []; - if (isColumnItem(actualArg)) { - if (actualArg.name) { - const { hit: columnCheck, nameHit } = columnExists(actualArg, references); - if (!columnCheck) { - if (argDef.constantOnly) { - messages.push( - getMessageFromId({ - messageId: 'expectedConstant', - values: { - fn: astFunction.name, - given: getUnknownTypeLabel(), - }, - locations: actualArg.location, - }) - ); - } else { - messages.push( - getMessageFromId({ - messageId: 'unknownColumn', - values: { - name: actualArg.name, - }, - locations: actualArg.location, - }) - ); - } - } else { - if (argDef.constantOnly) { - messages.push( - getMessageFromId({ - messageId: 'expectedConstant', - values: { - fn: astFunction.name, - given: actualArg.name, - }, - locations: actualArg.location, - }) - ); - } - if (actualArg.name === '*') { - // if function does not support wildcards return a specific error - if (!('supportsWildcard' in argDef) || !argDef.supportsWildcard) { - messages.push( - getMessageFromId({ - messageId: 'noWildcardSupportAsArg', - values: { - name: astFunction.name, - }, - locations: actualArg.location, - }) - ); - } - // do not validate any further for now, only count() accepts wildcard as args... - } else { - if (!isEqualType(actualArg, argDef, references, parentCommand, nameHit)) { - // guaranteed by the check above - const columnHit = getColumnHit(nameHit!, references); - messages.push( - getMessageFromId({ - messageId: 'wrongArgumentType', - values: { - name: astFunction.name, - argType: argDef.type, - value: actualArg.name, - givenType: columnHit!.type, - }, - locations: actualArg.location, - }) - ); - } - } - } + if (!isColumnItem(actualArg)) { + return messages; + } + + const columnName = getQuotedColumnName(actualArg); + const columnExists = getColumnExists(actualArg, references); + + if (parameterDefinition.constantOnly) { + messages.push( + getMessageFromId({ + messageId: 'expectedConstant', + values: { + fn: astFunction.name, + given: columnName, + }, + locations: actualArg.location, + }) + ); + + return messages; + } + + if (!columnExists) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: actualArg.name, + }, + locations: actualArg.location, + }) + ); + + return messages; + } + + if (actualArg.name === '*') { + // if function does not support wildcards return a specific error + if (!('supportsWildcard' in parameterDefinition) || !parameterDefinition.supportsWildcard) { + messages.push( + getMessageFromId({ + messageId: 'noWildcardSupportAsArg', + values: { + name: astFunction.name, + }, + locations: actualArg.location, + }) + ); } + + return messages; } + + if ( + !checkFunctionArgMatchesDefinition(actualArg, parameterDefinition, references, parentCommand) + ) { + const columnHit = lookupColumn(actualArg, references); + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: parameterDefinition.type, + value: actualArg.name, + givenType: columnHit!.type, + }, + locations: actualArg.location, + }) + ); + } + return messages; } @@ -292,6 +325,13 @@ function extractCompatibleSignaturesForFunction( }); } +function removeInlineCasts(arg: ESQLAstItem): ESQLAstItem { + if (isInlineCastItem(arg)) { + return removeInlineCasts(arg.value); + } + return arg; +} + function validateFunction( astFunction: ESQLFunction, parentCommand: string, @@ -396,7 +436,15 @@ function validateFunction( return signature.params[i]?.constantOnly; }); const wrappedArray = Array.isArray(arg) ? arg : [arg]; - for (const subArg of wrappedArray) { + for (const _subArg of wrappedArray) { + /** + * we need to remove the inline casts + * to see if there's a function under there + * + * e.g. for ABS(CEIL(numberField)::int), we need to validate CEIL(numberField) + */ + const subArg = removeInlineCasts(_subArg); + if (isFunctionItem(subArg)) { const messagesFromArg = validateFunction( subArg, @@ -473,6 +521,7 @@ function validateFunction( validateFunctionLiteralArg, validateNestedFunctionArg, validateFunctionColumnArg, + validateInlineCastArg, ].flatMap((validateFn) => { return validateFn( astFunction, @@ -682,14 +731,14 @@ function validateColumnForCommand( ); } } else { - const { hit: columnCheck, nameHit } = columnExists(column, references); - if (columnCheck && nameHit) { + const columnName = getQuotedColumnName(column); + if (getColumnExists(column, references)) { const commandDef = getCommandDefinition(commandName); const columnParamsWithInnerTypes = commandDef.signature.params.filter( ({ type, innerType }) => type === 'column' && innerType ); // this should be guaranteed by the columnCheck above - const columnRef = getColumnHit(nameHit, references)!; + const columnRef = lookupColumn(column, references)!; if (columnParamsWithInnerTypes.length) { const hasSomeWrongInnerTypes = columnParamsWithInnerTypes.every(({ innerType }) => { @@ -706,7 +755,7 @@ function validateColumnForCommand( type: supportedTypes.join(', '), typeCount: supportedTypes.length, givenType: columnRef.type, - column: nameHit, + column: columnName, }, locations: column.location, }) @@ -714,7 +763,7 @@ function validateColumnForCommand( } } if ( - hasWildcard(nameHit) && + hasWildcard(columnName) && !isVariable(columnRef) && !commandDef.signature.params.some(({ type, wildcards }) => type === 'column' && wildcards) ) { @@ -723,7 +772,7 @@ function validateColumnForCommand( messageId: 'wildcardNotSupportedForCommand', values: { command: commandName.toUpperCase(), - value: nameHit, + value: columnName, }, locations: column.location, }) From 92e70949f2b4ecb162c223e7c62a41052bc32ca8 Mon Sep 17 00:00:00 2001 From: Jill Guyonnet Date: Tue, 18 Jun 2024 13:52:39 +0100 Subject: [PATCH 047/127] [Fleet] Mark new Fleet-managed tags SO with `managed: true` (#185972) ## Summary Closes https://github.com/elastic/kibana/issues/176924 This is part 1 of making all Fleet-managed tags with the `managed: true` property in the Saved Object. With this change, new tags are created with `managed: true`. As discussed in https://github.com/elastic/kibana/issues/176924, a followup effort will be required to backfill existing tags. ### Steps to reproduce 1. Boot up a fresh ES instance with no prior data and start Kibana on `main`. 2. Go to Stack Management -> Tags: there should be no pre-existing tags. 3. In Fleet, create an agent policy with the System integration. 4. Go back to Stack Management -> Tags: there should be 4 non-managed tags: Screenshot 2024-06-13 at 16 22 39 5. Check out this branch and restart Kibana. 6. Install another integration, e.g. Apache HTTP Server. 7. Go back to Stack Management -> Tags: a new tag should have been created for the new integration. This tag should be managed and not editable in the UI: Screenshot 2024-06-13 at 16 25 53 8. (Optional): you can also check that this works for a new stack by starting a fresh ES instance and Kibana on this branch. In step 4 above, the 4 tags created after creating the agent policy with System should all be managed and not editable: Screenshot 2024-06-13 at 16 29 22 NB: the 4 tags created in the flow above reflect 3 different types of tag: - the `Managed` tag which all package assets are tagged with - package tags (`Elastic Agent` and `System` in this case) - tags defined in the integration's `tag.yml` ([in system's case](https://github.com/elastic/integrations/blob/main/packages/system/kibana/tags.yml), that's `Security Solution`) ### Checklist - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../saved_objects_tagging_oss/common/types.ts | 1 + .../epm/kibana/assets/tag_assets.test.ts | 48 +++++++++++++------ .../services/epm/kibana/assets/tag_assets.ts | 6 +-- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/plugins/saved_objects_tagging_oss/common/types.ts b/src/plugins/saved_objects_tagging_oss/common/types.ts index 58384465027c6..f72aabfb7fd02 100644 --- a/src/plugins/saved_objects_tagging_oss/common/types.ts +++ b/src/plugins/saved_objects_tagging_oss/common/types.ts @@ -30,6 +30,7 @@ export interface CreateTagOptions { id?: string; overwrite?: boolean; refresh?: boolean | 'wait_for'; + managed?: boolean; } export interface ITagsClient { diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts index f3d59c9607a38..82989715be0e1 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts @@ -24,7 +24,12 @@ describe('tagKibanaAssets', () => { description: '', name: 'Managed', }; - const managedTagPayloadArg2 = { id: 'fleet-managed-default', overwrite: true, refresh: false }; + const managedTagPayloadArg2 = { + id: 'fleet-managed-default', + overwrite: true, + refresh: false, + managed: true, + }; beforeEach(() => { savedObjectTagAssignmentService.updateTagAssignments.mockReset(); @@ -55,7 +60,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#0077CC', }, - { id: 'fleet-managed-default', overwrite: true, refresh: false } + { id: 'fleet-managed-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( { @@ -63,7 +68,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#4DD2CA', }, - { id: 'fleet-pkg-system-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-system-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledWith({ tags: ['fleet-managed-default', 'fleet-pkg-system-default'], @@ -201,7 +206,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#0077CC', }, - { id: 'fleet-managed-default', overwrite: true, refresh: false } + { id: 'fleet-managed-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( @@ -210,7 +215,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#4DD2CA', }, - { id: 'fleet-pkg-system-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-system-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledWith({ tags: ['managed', 'fleet-pkg-system-default'], @@ -248,7 +253,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#0077CC', }, - { id: 'fleet-managed-default', overwrite: true, refresh: false } + { id: 'fleet-managed-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).not.toHaveBeenCalledWith( @@ -257,7 +262,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#4DD2CA', }, - { id: 'system', overwrite: true, refresh: false } + { id: 'system', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledWith({ tags: ['fleet-managed-default', 'system'], @@ -339,7 +344,7 @@ describe('tagKibanaAssets', () => { description: '', name: 'TestPackage', }, - { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( { @@ -351,6 +356,7 @@ describe('tagKibanaAssets', () => { id: FOO_TAG_ID, overwrite: true, refresh: false, + managed: true, } ); expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledTimes(3); @@ -436,7 +442,7 @@ describe('tagKibanaAssets', () => { description: '', name: 'TestPackage', }, - { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( { @@ -448,6 +454,7 @@ describe('tagKibanaAssets', () => { id: BAR_TAG_ID, overwrite: true, refresh: false, + managed: true, } ); expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledTimes(3); @@ -538,7 +545,7 @@ describe('tagKibanaAssets', () => { description: '', name: 'TestPackage', }, - { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( { @@ -550,6 +557,7 @@ describe('tagKibanaAssets', () => { id: MY_CUSTOM_TAG_ID, overwrite: true, refresh: false, + managed: true, } ); expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledTimes(3); @@ -684,7 +692,7 @@ describe('tagKibanaAssets', () => { description: '', color: '#4DD2CA', }, - { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false, managed: true } ); }); @@ -728,7 +736,7 @@ describe('tagKibanaAssets', () => { description: '', name: 'TestPackage', }, - { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false } + { id: 'fleet-pkg-test-pkg-default', overwrite: true, refresh: false, managed: true } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( { @@ -736,7 +744,7 @@ describe('tagKibanaAssets', () => { description: 'Tag defined in package-spec', name: 'Security Solution', }, - { id: 'security-solution-default', overwrite: true, refresh: false } + { id: 'security-solution-default', overwrite: true, refresh: false, managed: true } ); }); @@ -779,7 +787,12 @@ describe('tagKibanaAssets', () => { description: '', name: 'TestPackage', }, - { id: 'fleet-pkg-test-pkg-my-secondary-space', overwrite: true, refresh: false } + { + id: 'fleet-pkg-test-pkg-my-secondary-space', + overwrite: true, + refresh: false, + managed: true, + } ); expect(savedObjectTagClient.create).toHaveBeenCalledWith( { @@ -787,7 +800,12 @@ describe('tagKibanaAssets', () => { description: 'Tag defined in package-spec', name: 'Security Solution', }, - { id: 'security-solution-my-secondary-space', overwrite: true, refresh: false } + { + id: 'security-solution-my-secondary-space', + overwrite: true, + refresh: false, + managed: true, + } ); }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts index 5e7d4477bbbd3..86127c19e2811 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts @@ -179,7 +179,7 @@ async function ensureManagedTag( description: '', color: MANAGED_TAG_COLOR, }, - { id: managedTagId, overwrite: true, refresh: false } + { id: managedTagId, overwrite: true, refresh: false, managed: true } ); return managedTagId; @@ -206,7 +206,7 @@ async function ensurePackageTag( description: '', color: PACKAGE_TAG_COLOR, }, - { id: packageTagId, overwrite: true, refresh: false } + { id: packageTagId, overwrite: true, refresh: false, managed: true } ); return packageTagId; @@ -232,7 +232,7 @@ async function getPackageSpecTags( description: 'Tag defined in package-spec', color: getRandomColor(), }, - { id: uniqueTagId, overwrite: true, refresh: false } + { id: uniqueTagId, overwrite: true, refresh: false, managed: true } ); } const assetTypes = getAssetTypesObjectReferences(tag?.asset_types, taggableAssets); From 27d967afcaf45645182f3ea129f2a145414d9f0d Mon Sep 17 00:00:00 2001 From: Jill Guyonnet Date: Tue, 18 Jun 2024 13:53:05 +0100 Subject: [PATCH 048/127] [Fleet] Fix serverless message in edit output flyout (#186183) ## Summary This PR fixes a bug where the message `Custom host URLs are not allowed in serverless.` is shown above the URL input in the flyout for editing the default Fleet Server host and default output. ### Screenshots #### Stateful Screenshot 2024-06-13 at 15 20 45 Screenshot 2024-06-13 at 15 20 54 #### Serverless Screenshot 2024-06-13 at 15 24 54 Screenshot 2024-06-13 at 15 25 02 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../edit_output_flyout/output_form_elasticsearch.tsx | 5 ++++- .../settings/components/fleet_server_hosts_flyout/index.tsx | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_elasticsearch.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_elasticsearch.tsx index 21e43fcba001a..bf79932416f5a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_elasticsearch.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_elasticsearch.tsx @@ -12,6 +12,8 @@ import { i18n } from '@kbn/i18n'; import { MultiRowInput } from '../multi_row_input'; +import { useStartServices } from '../../../../hooks'; + import type { OutputFormInputsType } from './use_output_form'; interface Props { @@ -20,6 +22,7 @@ interface Props { export const OutputFormElasticsearchSection: React.FunctionComponent = (props) => { const { inputs } = props; + const { cloud } = useStartServices(); return ( <> @@ -37,7 +40,7 @@ export const OutputFormElasticsearchSection: React.FunctionComponent = (p {...inputs.elasticsearchUrlInput.props} isUrl helpText={ - inputs.elasticsearchUrlInput.props.disabled && ( + cloud?.isServerlessEnabled && ( Date: Tue, 18 Jun 2024 13:53:56 +0100 Subject: [PATCH 049/127] [Fleet] Fix KQL filtering (#183757) ## Summary Closes https://github.com/elastic/kibana/issues/178069 This PR fixes agent policies KQL filtering in Fleet UI. Because agent policy data is retrieved from Saved Objects, the policy fields require the SO prefix (`ingest-agent-policies`), which was removed in https://github.com/elastic/kibana/pull/161064, to be present (see https://github.com/elastic/kibana/issues/178069#issuecomment-2154800178 for details). [A further ER](https://github.com/elastic/kibana/issues/185921) captures the requirements for displaying custom labels without the prefix. In Fleet UI, the `SearchBar` component that uses KQL filtering is used in three tabs: - Agents - Agent policies - Enrollment tokens Note that the search inputs in the Uninstall tokens and Data streams tabs are simple text filtering, not KQL. The filtering behaviour with this fix matches the one in 8.11.0 and is captured in the screen recording below: - Agents tab: agent fields (e.g. `policy_id` or `agent.version`) - Agent policies tab: agent policy fields prefixed with `ingest-agent-policies` (e.g. `ingest-agent-policies.name`) - Enrollment tokens tab: token fields (e.g. `name` or `policy_id`) ### Screen recording This screen recording shows working KQL filtering and suggestions for the three tabs (fixed for Agent policies): https://github.com/elastic/kibana/assets/23701614/db4a7de7-a098-497a-a3c8-075ed5d0425e ### Testing 1. Create a few agent policies and enroll a couple of agents. 2. Test that the expected fields are shown in the KQL search bars for agents, agent policies and enrollment tokens. For each, check that suggestions are shown when you select a particular field with existing values. 3. For agent policies in particular, also check that KQL syntax works as expect. For instance, if you have an agent policy named "Test agent policy", the query `ingest-agent-policies.name : *agent*` should correctly filter for it. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet/components/search_bar.test.tsx | 71 +++++++++---------- .../fleet/components/search_bar.tsx | 60 +++++++++------- .../sections/agent_policy/list_page/index.tsx | 6 +- .../components/search_and_filter_bar.tsx | 4 +- .../enrollment_token_list_page/index.tsx | 4 +- .../plugins/fleet/public/constants/index.ts | 4 ++ 6 files changed, 81 insertions(+), 68 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.test.tsx index c33a0427b5000..d572a00ec2241 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.test.tsx @@ -15,8 +15,11 @@ import { createFleetTestRendererMock } from '../../../mock'; import { AGENTS_PREFIX, FLEET_ENROLLMENT_API_PREFIX, - PACKAGE_POLICY_SAVED_OBJECT_TYPE, AGENT_POLICY_SAVED_OBJECT_TYPE, + AGENTS_INDEX, + ENROLLMENT_API_KEYS_INDEX, + INGEST_SAVED_OBJECT_INDEX, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, } from '../constants'; import { SearchBar, getFieldSpecs } from './search_bar'; @@ -169,13 +172,12 @@ describe('SearchBar', () => { }); describe('getFieldSpecs', () => { - it('returns fieldSpecs for fleet-agents', () => { - expect(getFieldSpecs(`.${AGENTS_PREFIX}`)).toHaveLength(67); + it('returns fieldSpecs for Fleet agents', () => { + expect(getFieldSpecs(AGENTS_INDEX, AGENTS_PREFIX)).toHaveLength(67); }); - it('returns getFieldSpecs for fleet-enrollment-api-keys', () => { - const indexPattern = `.${FLEET_ENROLLMENT_API_PREFIX}`; - expect(getFieldSpecs(indexPattern)).toHaveLength(8); - expect(getFieldSpecs(indexPattern)).toEqual([ + + it('returns fieldSpecs for Fleet enrollment tokens', () => { + expect(getFieldSpecs(ENROLLMENT_API_KEYS_INDEX, FLEET_ENROLLMENT_API_PREFIX)).toEqual([ { aggregatable: true, esTypes: ['boolean'], @@ -235,176 +237,173 @@ describe('getFieldSpecs', () => { ]); }); - it('returns getFieldSpecs for fleet-agent-policy', () => { - const indexPattern = `.${AGENT_POLICY_SAVED_OBJECT_TYPE}`; - expect(getFieldSpecs(indexPattern)).toHaveLength(23); - expect(getFieldSpecs(indexPattern)).toEqual([ + it('returns fieldSpecs for Fleet agent policies', () => { + expect(getFieldSpecs(INGEST_SAVED_OBJECT_INDEX, AGENT_POLICY_SAVED_OBJECT_TYPE)).toEqual([ { aggregatable: true, esTypes: ['keyword'], - name: 'agent_features.name', + name: 'ingest-agent-policies.agent_features.name', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['boolean'], - name: 'agent_features.enabled', + name: 'ingest-agent-policies.agent_features.enabled', searchable: true, type: 'boolean', }, { aggregatable: true, esTypes: ['keyword'], - name: 'data_output_id', + name: 'ingest-agent-policies.data_output_id', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['text'], - name: 'description', + name: 'ingest-agent-policies.description', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['keyword'], - name: 'download_source_id', + name: 'ingest-agent-policies.download_source_id', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['keyword'], - name: 'fleet_server_host_id', + name: 'ingest-agent-policies.fleet_server_host_id', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['integer'], - name: 'inactivity_timeout', + name: 'ingest-agent-policies.inactivity_timeout', searchable: true, type: 'number', }, { aggregatable: true, esTypes: ['boolean'], - name: 'is_default', + name: 'ingest-agent-policies.is_default', searchable: true, type: 'boolean', }, { aggregatable: true, esTypes: ['boolean'], - name: 'is_default_fleet_server', + name: 'ingest-agent-policies.is_default_fleet_server', searchable: true, type: 'boolean', }, { aggregatable: true, esTypes: ['boolean'], - name: 'is_managed', + name: 'ingest-agent-policies.is_managed', searchable: true, type: 'boolean', }, { aggregatable: true, esTypes: ['keyword'], - name: 'is_preconfigured', + name: 'ingest-agent-policies.is_preconfigured', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['boolean'], - name: 'is_protected', + name: 'ingest-agent-policies.is_protected', searchable: true, type: 'boolean', }, { aggregatable: true, esTypes: ['keyword'], - name: 'monitoring_enabled', + name: 'ingest-agent-policies.monitoring_enabled', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['false'], - name: 'monitoring_enabled.index', + name: 'ingest-agent-policies.monitoring_enabled.index', searchable: true, type: 'false', }, { aggregatable: true, esTypes: ['keyword'], - name: 'monitoring_output_id', + name: 'ingest-agent-policies.monitoring_output_id', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['keyword'], - name: 'name', + name: 'ingest-agent-policies.name', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['keyword'], - name: 'namespace', + name: 'ingest-agent-policies.namespace', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['integer'], - name: 'revision', + name: 'ingest-agent-policies.revision', searchable: true, type: 'number', }, { aggregatable: true, esTypes: ['version'], - name: 'schema_version', + name: 'ingest-agent-policies.schema_version', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['keyword'], - name: 'status', + name: 'ingest-agent-policies.status', searchable: true, type: 'string', }, { aggregatable: true, esTypes: ['integer'], - name: 'unenroll_timeout', + name: 'ingest-agent-policies.unenroll_timeout', searchable: true, type: 'number', }, { aggregatable: true, esTypes: ['date'], - name: 'updated_at', + name: 'ingest-agent-policies.updated_at', searchable: true, type: 'date', }, { aggregatable: true, esTypes: ['keyword'], - name: 'updated_by', + name: 'ingest-agent-policies.updated_by', searchable: true, type: 'string', }, ]); }); - expect(getFieldSpecs(`.${PACKAGE_POLICY_SAVED_OBJECT_TYPE}`)).toHaveLength(19); it('returns empty array if indexPattern is not one of the previous', async () => { - expect(getFieldSpecs('.kibana_ingest')).toEqual([]); + expect(getFieldSpecs(INGEST_SAVED_OBJECT_INDEX, PACKAGE_POLICY_SAVED_OBJECT_TYPE)).toEqual([]); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx index 6f23d25f38125..3e47a3a7955b3 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx @@ -16,19 +16,15 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import { i18n } from '@kbn/i18n'; import { useStartServices } from '../hooks'; -import { - INDEX_NAME, - AGENTS_PREFIX, - FLEET_ENROLLMENT_API_PREFIX, - PACKAGE_POLICY_SAVED_OBJECT_TYPE, - AGENT_POLICY_SAVED_OBJECT_TYPE, -} from '../constants'; import { AGENT_POLICY_MAPPINGS, - PACKAGE_POLICIES_MAPPINGS, AGENT_MAPPINGS, ENROLLMENT_API_KEY_MAPPINGS, -} from '../../../../common/constants'; + AGENTS_INDEX, + ENROLLMENT_API_KEYS_INDEX, + AGENT_POLICY_SAVED_OBJECT_TYPE, + INGEST_SAVED_OBJECT_INDEX, +} from '../constants'; const NoWrapQueryStringInput = styled(QueryStringInput)` .kbnQueryBar__textarea { @@ -38,29 +34,42 @@ const NoWrapQueryStringInput = styled(QueryStringInput)` interface Props { value: string; - fieldPrefix?: string; + indexPattern: string; + fieldPrefix: string; onChange: (newValue: string, submit?: boolean) => void; placeholder?: string; - indexPattern?: string; dataTestSubj?: string; } -const getMappings = (indexPattern: string) => { +const getMappings = (indexPattern: string, fieldPrefix: string) => { switch (indexPattern) { - case `.${AGENTS_PREFIX}`: + case AGENTS_INDEX: return AGENT_MAPPINGS; - case `.${AGENT_POLICY_SAVED_OBJECT_TYPE}`: - return AGENT_POLICY_MAPPINGS; - case `.${PACKAGE_POLICY_SAVED_OBJECT_TYPE}`: - return PACKAGE_POLICIES_MAPPINGS; - case `.${FLEET_ENROLLMENT_API_PREFIX}`: + // Saved Objects are stored in .kibana_ingest. + // Currently, the search bar is only used to query agent policies. + case INGEST_SAVED_OBJECT_INDEX: + switch (fieldPrefix) { + case AGENT_POLICY_SAVED_OBJECT_TYPE: + return AGENT_POLICY_MAPPINGS; + default: + return {}; + } + case ENROLLMENT_API_KEYS_INDEX: return ENROLLMENT_API_KEY_MAPPINGS; default: return {}; } }; -const getType = (type: string) => { +const getFieldName = (indexPattern: string, fieldPrefix: string, name: string) => { + // Add Saved Object prefix if the field refers to a SO and is not already prefixed. + if (indexPattern !== INGEST_SAVED_OBJECT_INDEX || name.startsWith(fieldPrefix)) { + return name; + } + return `${fieldPrefix}.${name}`; +}; + +const getFieldType = (type: string) => { switch (type) { case 'keyword': return 'string'; @@ -88,9 +97,10 @@ const concatKeys = (obj: any, parentKey = '') => { } return result; }; + /** Exported for testing only **/ -export const getFieldSpecs = (indexPattern: string) => { - const mapping = getMappings(indexPattern); +export const getFieldSpecs = (indexPattern: string, fieldPrefix: string) => { + const mapping = getMappings(indexPattern, fieldPrefix); // @ts-ignore-next-line const rawFields = concatKeys(mapping?.properties) || []; const fields = rawFields @@ -100,8 +110,8 @@ export const getFieldSpecs = (indexPattern: string) => { const fieldSpecs: FieldSpec[] = fields.map((field) => { return { - name: field[0], - type: getType(field[1]), + name: getFieldName(indexPattern, fieldPrefix, field[0]), + type: getFieldType(field[1]), searchable: true, aggregatable: true, esTypes: [field[1]], @@ -115,7 +125,7 @@ export const SearchBar: React.FunctionComponent = ({ fieldPrefix, onChange, placeholder, - indexPattern = INDEX_NAME, + indexPattern, dataTestSubj, }) => { const { @@ -148,7 +158,7 @@ export const SearchBar: React.FunctionComponent = ({ useEffect(() => { const fetchFields = async () => { try { - const fieldSpecs = getFieldSpecs(indexPattern); + const fieldSpecs = getFieldSpecs(indexPattern, fieldPrefix); const fieldsMap = data.dataViews.fieldArrayToMap(fieldSpecs); const newDataView = await data.dataViews.create( { title: indexPattern, fields: fieldsMap }, diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/index.tsx index a2e0e6663e5cf..40f057b56551c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/index.tsx @@ -25,7 +25,7 @@ import { useHistory } from 'react-router-dom'; import type { AgentPolicy } from '../../../types'; import { getRootIntegrations } from '../../../../../../common/services'; -import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../../../constants'; +import { AGENT_POLICY_SAVED_OBJECT_TYPE, INGEST_SAVED_OBJECT_INDEX } from '../../../constants'; import { useAuthz, usePagination, @@ -320,6 +320,8 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { { setPagination({ ...pagination, @@ -327,8 +329,6 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { }); setSearch(newSearch); }} - indexPattern={`.${AGENT_POLICY_SAVED_OBJECT_TYPE}`} - fieldPrefix={AGENT_POLICY_SAVED_OBJECT_TYPE} dataTestSubj="agentPolicyList.queryInput" /> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx index b0f6223193170..718684606f9d7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx @@ -163,14 +163,14 @@ export const SearchAndFilterBar: React.FunctionComponent { onDraftKueryChange(newSearch); if (submit) { onSubmitSearch(newSearch); } }} - fieldPrefix={AGENTS_PREFIX} - indexPattern={AGENTS_INDEX} dataTestSubj="agentList.queryInput" /> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/index.tsx index b72794868a1c2..3a21103503ae5 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/index.tsx @@ -245,6 +245,8 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { { setPagination({ ...pagination, @@ -252,8 +254,6 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { }); setSearch(newSearch); }} - indexPattern={ENROLLMENT_API_KEYS_INDEX} - fieldPrefix={FLEET_ENROLLMENT_API_PREFIX} dataTestSubj="enrollmentKeysList.queryInput" /> diff --git a/x-pack/plugins/fleet/public/constants/index.ts b/x-pack/plugins/fleet/public/constants/index.ts index ee01037f25a78..1c0a04b9cb8a7 100644 --- a/x-pack/plugins/fleet/public/constants/index.ts +++ b/x-pack/plugins/fleet/public/constants/index.ts @@ -28,6 +28,10 @@ export { AUTO_UPGRADE_POLICIES_PACKAGES, LOCATORS_IDS, FLEET_ENROLLMENT_API_PREFIX, + INGEST_SAVED_OBJECT_INDEX, + AGENT_POLICY_MAPPINGS, + AGENT_MAPPINGS, + ENROLLMENT_API_KEY_MAPPINGS, } from '../../common/constants'; export * from './page_paths'; From b98fc1418bfd607fa5ff983055f762a8cd50fb8b Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 18 Jun 2024 08:13:09 -0500 Subject: [PATCH 050/127] [ci] Prevent alerts for spot preemptions (#186329) After migrating to gobld, the string identifying spot instances has changed. This updates the check to determine if there are retries available by filtering on the metadata for both gobld and buildkite-agent-manager. --- .buildkite/pipeline-utils/buildkite/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/pipeline-utils/buildkite/client.ts b/.buildkite/pipeline-utils/buildkite/client.ts index be2cb81dd51c0..c58c3cb7e42e3 100644 --- a/.buildkite/pipeline-utils/buildkite/client.ts +++ b/.buildkite/pipeline-utils/buildkite/client.ts @@ -282,7 +282,7 @@ export class BuildkiteClient { hasRetries = true; const isPreemptionFailure = job.state === 'failed' && - job.agent?.meta_data?.includes('spot=true') && + job.agent?.meta_data?.some((el) => ['spot=true', 'gcp:preemptible=true'].includes(el)) && job.exit_status === -1; if (!isPreemptionFailure) { From c8bd58c9759626b96e6276595363f62800dc4d4d Mon Sep 17 00:00:00 2001 From: Miriam <31922082+MiriamAparicio@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:18:43 +0100 Subject: [PATCH 051/127] [ObsUX][Infra] Fix container metrics not showing correct fields for docker (#186363) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Some conditions were not correct on the render of the KPI, this didn’t show in the e2e tests because with synthtrace we just generate data for docker without kubernetes fields so it will be always showing docker fields. Apparently is possible to have both docker and k8s fields (kubernetes.container & docker.container), at least on the test data we have on the oblt-clusters. What we did is check if docker.container or kubernetes.container exist, in case of none, charts will not display, in case of both we show docker metric charts, otherwise k8s metrics charts For the metrics section the condition was correct but not for the KPIs --- .../components/kpis/container_kpi_charts.tsx | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx index 26ecccc7f1541..c2f61b97257fc 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx @@ -44,24 +44,30 @@ export const ContainerKpiCharts = ({ if (!isDockerContainer && !isKubernetesContainer) { return null; } - return isKubernetesContainer ? ( - - ) : ( - + + return ( + <> + {isDockerContainer && ( + + )} + {!isDockerContainer && isKubernetesContainer && ( + + )} + ); }; From c34bb46c8aeb59dca0c92132dd34d2d9fca68728 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 18 Jun 2024 14:27:26 +0100 Subject: [PATCH 052/127] [Entity Analytics] Flaky Cypress test fixes (#186081) ### Fix 1: Press refresh button after using date picker on dashboard Closes https://github.com/elastic/kibana/issues/183662 Closes https://github.com/elastic/kibana/issues/183635 Closes https://github.com/elastic/kibana/issues/183982 We shouldnt have to do this, but there is some condition where clicking apply gets the UI in a stuck state and I cant figure it out. ### Fix 2: Use more specific selector for search bar on risk score preview page Closes https://github.com/elastic/kibana/issues/184133 We were using a generic selector `[data-test-subj="unifiedQueryInput"] textarea` which was bringing back two elements sometimes (no idea why), I have given the box its own dedicated selector to hopefully prevent this from happening --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/risk_score_preview_section.tsx | 1 + .../dashboards/entity_analytics/new_risk_score.cy.ts | 2 ++ .../entity_analytics_management_page.cy.ts | 9 ++++----- .../cypress/screens/entity_analytics_management.ts | 3 +++ .../cypress/tasks/entity_analytics.ts | 6 +++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx index 91383fcdfd658..b8f7870e23b56 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx @@ -227,6 +227,7 @@ const RiskEnginePreview = () => { showDatePicker={true} displayStyle={'inPage'} submitButtonStyle={'iconOnly'} + dataTestSubj="risk-score-preview-search-bar-input" /> )} diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/entity_analytics/new_risk_score.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/entity_analytics/new_risk_score.cy.ts index 894248f9ff716..da59afaec941c 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/entity_analytics/new_risk_score.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/dashboards/entity_analytics/new_risk_score.cy.ts @@ -103,6 +103,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@serverless'] }, () => describe('With host risk data', () => { before(() => { + cy.task('esArchiverUnload', { archiveName: 'risk_scores_new' }); cy.task('esArchiverLoad', { archiveName: 'risk_scores_new' }); }); @@ -145,6 +146,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@serverless'] }, () => describe('With alerts data', () => { before(() => { + deleteAlertsAndRules(); createRule(getNewRule()); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts index fae26fec77fa2..b8d222471c87e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts @@ -15,6 +15,7 @@ import { LOCAL_QUERY_BAR_SELECTOR, RISK_SCORE_ERROR_PANEL, RISK_SCORE_STATUS, + LOCAL_QUERY_BAR_SEARCH_INPUT_SELECTOR, } from '../../screens/entity_analytics_management'; import { deleteRiskScore, installRiskScoreModule } from '../../tasks/api_calls/risk_scores'; @@ -31,7 +32,7 @@ import { interceptRiskInitError, } from '../../tasks/api_calls/risk_engine'; import { updateDateRangeInLocalDatePickers } from '../../tasks/date_picker'; -import { fillLocalSearchBar, submitLocalSearch } from '../../tasks/search_bar'; +import { submitLocalSearch } from '../../tasks/search_bar'; import { riskEngineStatusChange, upgradeRiskEngine, @@ -63,8 +64,7 @@ describe( cy.get(PAGE_TITLE).should('have.text', 'Entity Risk Score'); }); - // FLAKY: https://github.com/elastic/kibana/issues/184133 - describe.skip('Risk preview', () => { + describe('Risk preview', () => { it('risk scores reacts on change in datepicker', () => { const START_DATE = 'Jan 18, 2019 @ 20:33:29.186'; const END_DATE = 'Jan 19, 2019 @ 20:33:29.186'; @@ -81,8 +81,7 @@ describe( it('risk scores reacts on change in search bar query', () => { cy.get(HOST_RISK_PREVIEW_TABLE_ROWS).should('have.length', 5); cy.get(USER_RISK_PREVIEW_TABLE_ROWS).should('have.length', 5); - - fillLocalSearchBar('host.name: "test-host1"'); + cy.get(LOCAL_QUERY_BAR_SEARCH_INPUT_SELECTOR).type('host.name: "test-host1"'); submitLocalSearch(LOCAL_QUERY_BAR_SELECTOR); cy.get(HOST_RISK_PREVIEW_TABLE_ROWS).should('have.length', 1); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/entity_analytics_management.ts b/x-pack/test/security_solution_cypress/cypress/screens/entity_analytics_management.ts index 481c12fd9232e..e1d62ffb420c8 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/entity_analytics_management.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/entity_analytics_management.ts @@ -23,6 +23,9 @@ export const RISK_PREVIEW_ERROR_BUTTON = '[data-test-subj="risk-preview-error-bu export const LOCAL_QUERY_BAR_SELECTOR = getDataTestSubjectSelector('risk-score-preview-search-bar'); +export const LOCAL_QUERY_BAR_SEARCH_INPUT_SELECTOR = + '[data-test-subj="risk-score-preview-search-bar-input"]'; + export const RISK_SCORE_ERROR_PANEL = '[data-test-subj="risk-score-error-panel"]'; export const RISK_SCORE_UPDATE_CANCEL = '[data-test-subj="risk-score-update-cancel"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/entity_analytics.ts b/x-pack/test/security_solution_cypress/cypress/tasks/entity_analytics.ts index bb02c196ac92e..5d84c28100fee 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/entity_analytics.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/entity_analytics.ts @@ -26,13 +26,13 @@ import { } from '../screens/entity_analytics_management'; import { visitWithTimeRange } from './navigation'; import { GET_DATE_PICKER_APPLY_BUTTON, GLOBAL_FILTERS_CONTAINER } from '../screens/date_picker'; -import { LOADING_SPINNER } from '../screens/loading'; +import { REFRESH_BUTTON } from '../screens/security_header'; export const updateDashboardTimeRange = () => { // eslint-disable-next-line cypress/no-force cy.get(GET_DATE_PICKER_APPLY_BUTTON(GLOBAL_FILTERS_CONTAINER)).click({ force: true }); // Force to fix global timerange flakiness - cy.get(LOADING_SPINNER).should('exist'); - cy.get(LOADING_SPINNER).should('not.exist'); + cy.get(REFRESH_BUTTON).click(); + cy.get(REFRESH_BUTTON).should('not.have.attr', 'aria-label', 'Needs updating'); }; export const waitForAnomaliesToBeLoaded = () => { From 51bc0dc039f1fc102f12e959e3f19715cc184a91 Mon Sep 17 00:00:00 2001 From: Ersin Erdal <92688503+ersin-erdal@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:31:16 +0200 Subject: [PATCH 053/127] Add connector and actionTaskParams modelVersions (#184542) Resolves: #177059 This PR adds model versions for `action` and `action_task_params` saved objects. I also re-organised the schema and model version file structure in alerting, task_manager and actions plugins. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../check_registered_types.test.ts | 4 +- .../actions/server/saved_objects/index.ts | 4 + .../action_task_params_model_versions.ts | 18 +++++ .../connector_model_versions.ts | 18 +++++ .../saved_objects/model_versions/index.ts | 9 +++ .../schemas/action_task_params/index.ts | 8 ++ .../schemas/action_task_params/v1.ts | 29 +++++++ .../schemas/raw_connector/index.ts | 8 ++ .../schemas/raw_connector/v1.test.ts} | 8 +- .../schemas/raw_connector/v1.ts} | 6 +- .../create_get_alert_indices_alias.test.ts | 1 - x-pack/plugins/alerting/server/plugin.ts | 2 - .../server/rule_type_registry.mock.ts | 1 - .../server/rule_type_registry.test.ts | 11 --- .../alerting/server/rule_type_registry.ts | 8 -- .../ad_hoc_run_params_model_versions.ts | 51 ------------ .../alerting/server/saved_objects/index.ts | 4 +- .../saved_objects/is_rule_exportable.test.ts | 1 - .../ad_hoc_run_params_model_versions.ts | 19 +++++ .../saved_objects/model_versions/index.ts | 9 +++ .../model_versions/rule_model_versions.ts | 18 +++++ .../saved_objects/rule_model_versions.test.ts | 77 ------------------- .../saved_objects/rule_model_versions.ts | 49 ------------ .../server/saved_objects/index.ts | 2 +- .../saved_objects/model_versions/index.ts | 8 ++ .../task_model_versions.ts | 2 +- 26 files changed, 161 insertions(+), 214 deletions(-) create mode 100644 x-pack/plugins/actions/server/saved_objects/model_versions/action_task_params_model_versions.ts create mode 100644 x-pack/plugins/actions/server/saved_objects/model_versions/connector_model_versions.ts create mode 100644 x-pack/plugins/actions/server/saved_objects/model_versions/index.ts create mode 100644 x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/index.ts create mode 100644 x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/v1.ts create mode 100644 x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/index.ts rename x-pack/plugins/actions/server/{raw_connector_schema.test.ts => saved_objects/schemas/raw_connector/v1.test.ts} (93%) rename x-pack/plugins/actions/server/{raw_connector_schema.ts => saved_objects/schemas/raw_connector/v1.ts} (73%) delete mode 100644 x-pack/plugins/alerting/server/saved_objects/ad_hoc_run_params_model_versions.ts create mode 100644 x-pack/plugins/alerting/server/saved_objects/model_versions/ad_hoc_run_params_model_versions.ts create mode 100644 x-pack/plugins/alerting/server/saved_objects/model_versions/index.ts create mode 100644 x-pack/plugins/alerting/server/saved_objects/model_versions/rule_model_versions.ts delete mode 100644 x-pack/plugins/alerting/server/saved_objects/rule_model_versions.test.ts delete mode 100644 x-pack/plugins/alerting/server/saved_objects/rule_model_versions.ts create mode 100644 x-pack/plugins/task_manager/server/saved_objects/model_versions/index.ts rename x-pack/plugins/task_manager/server/saved_objects/{ => model_versions}/task_model_versions.ts (92%) diff --git a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts index c89ca689dbfc8..2337bbfaaa89e 100644 --- a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts +++ b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts @@ -55,8 +55,8 @@ describe('checking migration metadata changes on all registered SO types', () => expect(hashMap).toMatchInlineSnapshot(` Object { - "action": "cc93fe2c0c76e57c2568c63170e05daea897c136", - "action_task_params": "96e27e7f4e8273ffcd87060221e2b75e81912dd5", + "action": "0e6fc0b74c7312a8c11ff6b14437b93a997358b8", + "action_task_params": "b50cb5c8a493881474918e8d4985e61374ca4c30", "ad_hoc_run_params": "d4e3c5c794151d0a4f5c71e886b2aa638da73ad2", "alert": "3a67d3f1db80af36bd57aaea47ecfef87e43c58f", "api_key_pending_invalidation": "1399e87ca37b3d3a65d269c924eda70726cfe886", diff --git a/x-pack/plugins/actions/server/saved_objects/index.ts b/x-pack/plugins/actions/server/saved_objects/index.ts index e39c3a4a8a383..a4d7886091fe5 100644 --- a/x-pack/plugins/actions/server/saved_objects/index.ts +++ b/x-pack/plugins/actions/server/saved_objects/index.ts @@ -13,6 +13,7 @@ import type { import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; import { getOldestIdleActionTask } from '@kbn/task-manager-plugin/server'; import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import { actionTaskParamsModelVersions } from './model_versions'; import { actionMappings, actionTaskParamsMappings, connectorTokenMappings } from './mappings'; import { getActionsMigrations } from './actions_migrations'; import { getActionTaskParamsMigrations } from './action_task_params_migrations'; @@ -25,6 +26,7 @@ import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, CONNECTOR_TOKEN_SAVED_OBJECT_TYPE, } from '../constants/saved_objects'; +import { connectorModelVersions } from './model_versions'; export function setupSavedObjects( savedObjects: SavedObjectsServiceSetup, @@ -60,6 +62,7 @@ export function setupSavedObjects( }; }, }, + modelVersions: connectorModelVersions, }); // Encrypted attributes @@ -94,6 +97,7 @@ export function setupSavedObjects( }, }; }, + modelVersions: actionTaskParamsModelVersions, }); encryptedSavedObjects.registerType({ type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, diff --git a/x-pack/plugins/actions/server/saved_objects/model_versions/action_task_params_model_versions.ts b/x-pack/plugins/actions/server/saved_objects/model_versions/action_task_params_model_versions.ts new file mode 100644 index 0000000000000..570ebff743c17 --- /dev/null +++ b/x-pack/plugins/actions/server/saved_objects/model_versions/action_task_params_model_versions.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; +import { actionTaskParamsSchemaV1 } from '../schemas/action_task_params'; + +export const actionTaskParamsModelVersions: SavedObjectsModelVersionMap = { + '1': { + changes: [], + schemas: { + create: actionTaskParamsSchemaV1, + }, + }, +}; diff --git a/x-pack/plugins/actions/server/saved_objects/model_versions/connector_model_versions.ts b/x-pack/plugins/actions/server/saved_objects/model_versions/connector_model_versions.ts new file mode 100644 index 0000000000000..03d305d26a086 --- /dev/null +++ b/x-pack/plugins/actions/server/saved_objects/model_versions/connector_model_versions.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; +import { rawConnectorSchemaV1 } from '../schemas/raw_connector'; + +export const connectorModelVersions: SavedObjectsModelVersionMap = { + '1': { + changes: [], + schemas: { + create: rawConnectorSchemaV1, + }, + }, +}; diff --git a/x-pack/plugins/actions/server/saved_objects/model_versions/index.ts b/x-pack/plugins/actions/server/saved_objects/model_versions/index.ts new file mode 100644 index 0000000000000..fdfc6adecd8e0 --- /dev/null +++ b/x-pack/plugins/actions/server/saved_objects/model_versions/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { connectorModelVersions } from './connector_model_versions'; +export { actionTaskParamsModelVersions } from './action_task_params_model_versions'; diff --git a/x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/index.ts b/x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/index.ts new file mode 100644 index 0000000000000..4ce0e679adf5e --- /dev/null +++ b/x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { actionTaskParamsSchema as actionTaskParamsSchemaV1 } from './v1'; diff --git a/x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/v1.ts b/x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/v1.ts new file mode 100644 index 0000000000000..ceef18ae2dd75 --- /dev/null +++ b/x-pack/plugins/actions/server/saved_objects/schemas/action_task_params/v1.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; + +export const actionTaskParamsSchema = schema.object({ + actionId: schema.string(), + executionId: schema.maybe(schema.string()), + apiKey: schema.nullable(schema.string()), + params: schema.recordOf(schema.string(), schema.maybe(schema.any()), { defaultValue: {} }), + consumer: schema.maybe(schema.string()), + source: schema.maybe(schema.string()), + relatedSavedObjects: schema.maybe( + schema.arrayOf( + schema.object({ + namespace: schema.maybe(schema.string({ minLength: 1 })), + id: schema.string({ minLength: 1 }), + type: schema.string({ minLength: 1 }), + // optional; for SO types like action/alert that have type id's + typeId: schema.maybe(schema.string({ minLength: 1 })), + }), + { defaultValue: [] } + ) + ), +}); diff --git a/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/index.ts b/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/index.ts new file mode 100644 index 0000000000000..f86d616c03393 --- /dev/null +++ b/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { rawConnectorSchema as rawConnectorSchemaV1 } from './v1'; diff --git a/x-pack/plugins/actions/server/raw_connector_schema.test.ts b/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/v1.test.ts similarity index 93% rename from x-pack/plugins/actions/server/raw_connector_schema.test.ts rename to x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/v1.test.ts index 80c8ba0cfef7c..ed2fe6b3a371c 100644 --- a/x-pack/plugins/actions/server/raw_connector_schema.test.ts +++ b/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/v1.test.ts @@ -5,18 +5,18 @@ * 2.0. */ -import { rawConnectorSchema } from './raw_connector_schema'; +import { rawConnectorSchema } from './v1'; const action = { actionTypeId: '12345', name: 'test-action-name', - isMissingSecrets: true, + isMissingSecrets: false, config: { foo: 'bar', }, - secrets: { + secrets: JSON.stringify({ pass: 'foo', - }, + }), isPreconfigured: false, isSystemAction: false, }; diff --git a/x-pack/plugins/actions/server/raw_connector_schema.ts b/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/v1.ts similarity index 73% rename from x-pack/plugins/actions/server/raw_connector_schema.ts rename to x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/v1.ts index e98b31aef177f..df1927972af89 100644 --- a/x-pack/plugins/actions/server/raw_connector_schema.ts +++ b/x-pack/plugins/actions/server/saved_objects/schemas/raw_connector/v1.ts @@ -11,8 +11,10 @@ export const rawConnectorSchema = schema.object({ actionTypeId: schema.string(), name: schema.string(), isMissingSecrets: schema.boolean(), - config: schema.recordOf(schema.string(), schema.any()), - secrets: schema.recordOf(schema.string(), schema.any()), + config: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + // Encrypted fields are saved as string. Decrypted version of the 'secrets' field is an object + secrets: schema.string({ defaultValue: '{}' }), + isPreconfigured: schema.maybe(schema.boolean()), isSystemAction: schema.maybe(schema.boolean()), id: schema.maybe(schema.string()), diff --git a/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts b/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts index 32fac87b7485b..9a8109977962c 100644 --- a/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts +++ b/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts @@ -33,7 +33,6 @@ describe('createGetAlertIndicesAliasFn', () => { licensing: licensingMock.createSetup(), minimumScheduleInterval: { value: '1m', enforce: false }, inMemoryMetrics, - latestRuleVersion: 1, }; const registry = new RuleTypeRegistry(ruleTypeRegistryParams); registry.register({ diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 884fa761526ea..1eb130f523c9c 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -79,7 +79,6 @@ import { registerAlertingUsageCollector } from './usage'; import { initializeAlertingTelemetry, scheduleAlertingTelemetry } from './usage/task'; import { setupSavedObjects, - getLatestRuleVersion, RULE_SAVED_OBJECT_TYPE, AD_HOC_RUN_SAVED_OBJECT_TYPE, } from './saved_objects'; @@ -333,7 +332,6 @@ export class AlertingPlugin { alertsService: this.alertsService, minimumScheduleInterval: this.config.rules.minimumScheduleInterval, inMemoryMetrics: this.inMemoryMetrics, - latestRuleVersion: getLatestRuleVersion(), }); this.ruleTypeRegistry = ruleTypeRegistry; diff --git a/x-pack/plugins/alerting/server/rule_type_registry.mock.ts b/x-pack/plugins/alerting/server/rule_type_registry.mock.ts index 0aa7e5b68b40c..706484fdd92f6 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.mock.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.mock.ts @@ -18,7 +18,6 @@ const createRuleTypeRegistryMock = () => { list: jest.fn(), getAllTypes: jest.fn(), ensureRuleTypeEnabled: jest.fn(), - getLatestRuleVersion: jest.fn(), }; return mocked; }; diff --git a/x-pack/plugins/alerting/server/rule_type_registry.test.ts b/x-pack/plugins/alerting/server/rule_type_registry.test.ts index 2059f1e7548e6..709533bb898f2 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.test.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.test.ts @@ -40,7 +40,6 @@ beforeEach(() => { licensing: licensingMock.createSetup(), minimumScheduleInterval: { value: '1m', enforce: false }, inMemoryMetrics, - latestRuleVersion: 1, }; }); @@ -913,16 +912,6 @@ describe('Create Lifecycle', () => { ).toThrowErrorMatchingInlineSnapshot(`"Fail"`); }); }); - - describe('getLatestRuleVersion', () => { - test('should return the latest rule version', async () => { - const ruleTypeRegistry = new RuleTypeRegistry({ - ...ruleTypeRegistryParams, - latestRuleVersion: 5, - }); - expect(ruleTypeRegistry.getLatestRuleVersion()).toBe(5); - }); - }); }); function ruleTypeWithVariables( diff --git a/x-pack/plugins/alerting/server/rule_type_registry.ts b/x-pack/plugins/alerting/server/rule_type_registry.ts index 79c959a62eedf..50ab1f113ab8b 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.ts @@ -50,7 +50,6 @@ export interface ConstructorOptions { minimumScheduleInterval: AlertingRulesConfig['minimumScheduleInterval']; inMemoryMetrics: InMemoryMetrics; alertsService: AlertsService | null; - latestRuleVersion: number; } export interface RegistryRuleType @@ -160,7 +159,6 @@ export class RuleTypeRegistry { private readonly licensing: LicensingPluginSetup; private readonly inMemoryMetrics: InMemoryMetrics; private readonly alertsService: AlertsService | null; - private readonly latestRuleVersion: number; constructor({ config, @@ -172,7 +170,6 @@ export class RuleTypeRegistry { minimumScheduleInterval, inMemoryMetrics, alertsService, - latestRuleVersion, }: ConstructorOptions) { this.config = config; this.logger = logger; @@ -183,7 +180,6 @@ export class RuleTypeRegistry { this.minimumScheduleInterval = minimumScheduleInterval; this.inMemoryMetrics = inMemoryMetrics; this.alertsService = alertsService; - this.latestRuleVersion = latestRuleVersion; } public has(id: string) { @@ -436,10 +432,6 @@ export class RuleTypeRegistry { public getAllTypes(): string[] { return [...this.ruleTypes.keys()]; } - - public getLatestRuleVersion() { - return this.latestRuleVersion; - } } function normalizedActionVariables(actionVariables: RuleType['actionVariables']) { diff --git a/x-pack/plugins/alerting/server/saved_objects/ad_hoc_run_params_model_versions.ts b/x-pack/plugins/alerting/server/saved_objects/ad_hoc_run_params_model_versions.ts deleted file mode 100644 index 10d8dc759e9be..0000000000000 --- a/x-pack/plugins/alerting/server/saved_objects/ad_hoc_run_params_model_versions.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SavedObjectsModelVersion, - SavedObjectsModelVersionMap, -} from '@kbn/core-saved-objects-server'; -import { AdHocRunSO } from '../data/ad_hoc_run/types'; -import { rawAdHocRunParamsSchemaV1 } from './schemas/raw_ad_hoc_run_params'; - -interface CustomSavedObjectsModelVersion extends SavedObjectsModelVersion { - isCompatibleWithPreviousVersion: (param: AdHocRunSO) => boolean; -} - -export interface CustomSavedObjectsModelVersionMap extends SavedObjectsModelVersionMap { - [modelVersion: string]: CustomSavedObjectsModelVersion; -} - -export const adHocRunParamsModelVersions: CustomSavedObjectsModelVersionMap = { - '1': { - changes: [], - schemas: { - forwardCompatibility: rawAdHocRunParamsSchemaV1.extends({}, { unknowns: 'ignore' }), - create: rawAdHocRunParamsSchemaV1, - }, - isCompatibleWithPreviousVersion: () => true, - }, -}; - -export const getLatestAdHocRunParamsVersion = () => - Math.max(...Object.keys(adHocRunParamsModelVersions).map(Number)); - -export function getMinimumCompatibleVersion( - modelVersions: CustomSavedObjectsModelVersionMap, - version: number, - adHocRunParam: AdHocRunSO -): number { - if (version === 1) { - return 1; - } - - if (modelVersions[version].isCompatibleWithPreviousVersion(adHocRunParam)) { - return getMinimumCompatibleVersion(modelVersions, version - 1, adHocRunParam); - } - - return version; -} diff --git a/x-pack/plugins/alerting/server/saved_objects/index.ts b/x-pack/plugins/alerting/server/saved_objects/index.ts index 0dd261c4c39f1..eb07a84950d14 100644 --- a/x-pack/plugins/alerting/server/saved_objects/index.ts +++ b/x-pack/plugins/alerting/server/saved_objects/index.ts @@ -24,13 +24,11 @@ import { getImportWarnings } from './get_import_warnings'; import { isRuleExportable } from './is_rule_exportable'; import { RuleTypeRegistry } from '../rule_type_registry'; export { partiallyUpdateRule } from './partially_update_rule'; -export { getLatestRuleVersion, getMinimumCompatibleVersion } from './rule_model_versions'; import { RULES_SETTINGS_SAVED_OBJECT_TYPE, MAINTENANCE_WINDOW_SAVED_OBJECT_TYPE, } from '../../common'; -import { ruleModelVersions } from './rule_model_versions'; -import { adHocRunParamsModelVersions } from './ad_hoc_run_params_model_versions'; +import { ruleModelVersions, adHocRunParamsModelVersions } from './model_versions'; export const RULE_SAVED_OBJECT_TYPE = 'alert'; export const AD_HOC_RUN_SAVED_OBJECT_TYPE = 'ad_hoc_run_params'; diff --git a/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts b/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts index 7ed188915c869..27145ecfe072f 100644 --- a/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts @@ -38,7 +38,6 @@ beforeEach(() => { licensing: licensingMock.createSetup(), minimumScheduleInterval: { value: '1m', enforce: false }, inMemoryMetrics, - latestRuleVersion: 1, }; }); diff --git a/x-pack/plugins/alerting/server/saved_objects/model_versions/ad_hoc_run_params_model_versions.ts b/x-pack/plugins/alerting/server/saved_objects/model_versions/ad_hoc_run_params_model_versions.ts new file mode 100644 index 0000000000000..95f544be5c8e2 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/model_versions/ad_hoc_run_params_model_versions.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; +import { rawAdHocRunParamsSchemaV1 } from '../schemas/raw_ad_hoc_run_params'; + +export const adHocRunParamsModelVersions: SavedObjectsModelVersionMap = { + '1': { + changes: [], + schemas: { + forwardCompatibility: rawAdHocRunParamsSchemaV1.extends({}, { unknowns: 'ignore' }), + create: rawAdHocRunParamsSchemaV1, + }, + }, +}; diff --git a/x-pack/plugins/alerting/server/saved_objects/model_versions/index.ts b/x-pack/plugins/alerting/server/saved_objects/model_versions/index.ts new file mode 100644 index 0000000000000..89c4f3a3cd2bb --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/model_versions/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { adHocRunParamsModelVersions } from './ad_hoc_run_params_model_versions'; +export { ruleModelVersions } from './rule_model_versions'; diff --git a/x-pack/plugins/alerting/server/saved_objects/model_versions/rule_model_versions.ts b/x-pack/plugins/alerting/server/saved_objects/model_versions/rule_model_versions.ts new file mode 100644 index 0000000000000..2d778667d2b79 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/model_versions/rule_model_versions.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; +import { rawRuleSchemaV1 } from '../schemas/raw_rule'; + +export const ruleModelVersions: SavedObjectsModelVersionMap = { + '1': { + changes: [], + schemas: { + create: rawRuleSchemaV1, + }, + }, +}; diff --git a/x-pack/plugins/alerting/server/saved_objects/rule_model_versions.test.ts b/x-pack/plugins/alerting/server/saved_objects/rule_model_versions.test.ts deleted file mode 100644 index 9afcdaad8e2f4..0000000000000 --- a/x-pack/plugins/alerting/server/saved_objects/rule_model_versions.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - CustomSavedObjectsModelVersionMap, - getLatestRuleVersion, - getMinimumCompatibleVersion, -} from './rule_model_versions'; -import { schema } from '@kbn/config-schema'; -import { RawRule } from '../types'; - -describe('rule model versions', () => { - const ruleModelVersions: CustomSavedObjectsModelVersionMap = { - '1': { - changes: [], - schemas: { - create: schema.object({ - name: schema.string(), - }), - }, - isCompatibleWithPreviousVersion: (rawRule) => true, - }, - '2': { - changes: [], - schemas: { - create: schema.object({ - name: schema.string(), - }), - }, - isCompatibleWithPreviousVersion: (rawRule) => false, - }, - '3': { - changes: [], - schemas: { - create: schema.object({ - name: schema.string(), - }), - }, - isCompatibleWithPreviousVersion: (rawRule) => rawRule.name === 'test', - }, - '4': { - changes: [], - schemas: { - create: schema.object({ - name: schema.string(), - }), - }, - isCompatibleWithPreviousVersion: (rawRule) => rawRule.name === 'test', - }, - }; - - const rawRule = { name: 'test' } as RawRule; - const mismatchingRawRule = { enabled: true } as RawRule; - - describe('getMinimumCompatibleVersion', () => { - it('should return the minimum compatible version for the matching rawRule', () => { - expect(getMinimumCompatibleVersion(ruleModelVersions, 1, rawRule)).toBe(1); - expect(getMinimumCompatibleVersion(ruleModelVersions, 2, rawRule)).toBe(2); - expect(getMinimumCompatibleVersion(ruleModelVersions, 3, rawRule)).toBe(2); - expect(getMinimumCompatibleVersion(ruleModelVersions, 4, rawRule)).toBe(2); - }); - it('should return the minimum compatible version for the mismatching rawRule', () => { - expect(getMinimumCompatibleVersion(ruleModelVersions, 3, mismatchingRawRule)).toBe(3); - expect(getMinimumCompatibleVersion(ruleModelVersions, 4, mismatchingRawRule)).toBe(4); - }); - }); - - describe('getLatestRuleVersion', () => { - it('should return the latest rule model version', () => { - expect(getLatestRuleVersion()).toBe(1); - }); - }); -}); diff --git a/x-pack/plugins/alerting/server/saved_objects/rule_model_versions.ts b/x-pack/plugins/alerting/server/saved_objects/rule_model_versions.ts deleted file mode 100644 index 38adc17389b23..0000000000000 --- a/x-pack/plugins/alerting/server/saved_objects/rule_model_versions.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SavedObjectsModelVersion, - SavedObjectsModelVersionMap, -} from '@kbn/core-saved-objects-server'; -import { RawRule } from '../types'; -import { rawRuleSchemaV1 } from './schemas/raw_rule'; - -interface CustomSavedObjectsModelVersion extends SavedObjectsModelVersion { - isCompatibleWithPreviousVersion: (param: RawRule) => boolean; -} - -export interface CustomSavedObjectsModelVersionMap extends SavedObjectsModelVersionMap { - [modelVersion: string]: CustomSavedObjectsModelVersion; -} - -export const ruleModelVersions: CustomSavedObjectsModelVersionMap = { - '1': { - changes: [], - schemas: { - create: rawRuleSchemaV1, - }, - isCompatibleWithPreviousVersion: (rawRule) => true, - }, -}; - -export const getLatestRuleVersion = () => Math.max(...Object.keys(ruleModelVersions).map(Number)); - -export function getMinimumCompatibleVersion( - modelVersions: CustomSavedObjectsModelVersionMap, - version: number, - rawRule: RawRule -): number { - if (version === 1) { - return 1; - } - - if (modelVersions[version].isCompatibleWithPreviousVersion(rawRule)) { - return getMinimumCompatibleVersion(modelVersions, version - 1, rawRule); - } - - return version; -} diff --git a/x-pack/plugins/task_manager/server/saved_objects/index.ts b/x-pack/plugins/task_manager/server/saved_objects/index.ts index 390990bd10dbf..68bc796d7aba3 100644 --- a/x-pack/plugins/task_manager/server/saved_objects/index.ts +++ b/x-pack/plugins/task_manager/server/saved_objects/index.ts @@ -7,12 +7,12 @@ import type { SavedObjectsServiceSetup } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { taskModelVersions } from './task_model_versions'; import { taskMappings } from './mappings'; import { getMigrations } from './migrations'; import { TaskManagerConfig } from '../config'; import { getOldestIdleActionTask } from '../queries/oldest_idle_action_task'; import { TASK_MANAGER_INDEX } from '../constants'; +import { taskModelVersions } from './model_versions'; export function setupSavedObjects( savedObjects: SavedObjectsServiceSetup, diff --git a/x-pack/plugins/task_manager/server/saved_objects/model_versions/index.ts b/x-pack/plugins/task_manager/server/saved_objects/model_versions/index.ts new file mode 100644 index 0000000000000..9d84e528a3d39 --- /dev/null +++ b/x-pack/plugins/task_manager/server/saved_objects/model_versions/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { taskModelVersions } from './task_model_versions'; diff --git a/x-pack/plugins/task_manager/server/saved_objects/task_model_versions.ts b/x-pack/plugins/task_manager/server/saved_objects/model_versions/task_model_versions.ts similarity index 92% rename from x-pack/plugins/task_manager/server/saved_objects/task_model_versions.ts rename to x-pack/plugins/task_manager/server/saved_objects/model_versions/task_model_versions.ts index adfebecf84dce..d76d26e56c23e 100644 --- a/x-pack/plugins/task_manager/server/saved_objects/task_model_versions.ts +++ b/x-pack/plugins/task_manager/server/saved_objects/model_versions/task_model_versions.ts @@ -6,7 +6,7 @@ */ import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; -import { taskSchemaV1 } from './schemas/task'; +import { taskSchemaV1 } from '../schemas/task'; export const taskModelVersions: SavedObjectsModelVersionMap = { '1': { From c49cfbea81f36abca2a04d32d8a4ad14585ef6bb Mon Sep 17 00:00:00 2001 From: Nikita Indik Date: Tue, 18 Jun 2024 16:41:16 +0200 Subject: [PATCH 054/127] [Security Solution] `DetectionRulesClient`: return `RuleResponse` from `createCustomRule` and `createPrebuiltRule` (#185748) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Partially addresses: https://github.com/elastic/kibana/issues/184364** ## Summary This PR changes `createCustomRule` and `createPrebuiltRule` methods to return `RuleResponse` instead of `RuleAlertType`. This is a continuation of the effort to improve `DetectionRulesClient`. As a part of it we want to make the client return `RuleResponse` from all its public methods. This is good because it lets us hide rule's internal structure and centralise conversions in one place – in the client. So in this and upcoming PRs we are going to convert `RuleAlertType` to `RuleResponse` within the client's methods and return the `RuleResponse` object. --- .../perform_rule_installation_route.ts | 3 +- .../rule_objects/create_prebuilt_rules.ts | 2 +- .../lib/detection_engine/routes/utils.test.ts | 19 +++++++++ .../lib/detection_engine/routes/utils.ts | 7 ++++ .../api/rules/bulk_create_rules/route.test.ts | 5 +-- .../api/rules/bulk_create_rules/route.ts | 4 +- .../api/rules/create_rule/route.test.ts | 5 +-- .../api/rules/create_rule/route.ts | 4 +- ...on_rules_client.create_custom_rule.test.ts | 21 ++++++++++ ..._rules_client.create_prebuilt_rule.test.ts | 39 +++++++++++-------- .../detection_rules_client.ts | 5 ++- .../detection_rules_client_interface.ts | 23 ++++++----- .../methods/create_custom_rule.ts | 22 ++++++++--- .../methods/create_prebuilt_rule.ts | 28 +++++++++---- .../logic/detection_rules_client/utils.ts | 19 +++++++++ 15 files changed, 149 insertions(+), 57 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts index 0399d3312de2f..8ffec60a26c11 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts @@ -19,7 +19,6 @@ import type { SecuritySolutionPluginRouter } from '../../../../../types'; import { buildRouteValidation } from '../../../../../utils/build_validation/route_validation'; import type { PromisePoolError } from '../../../../../utils/promise_pool'; import { buildSiemResponse } from '../../../routes/utils'; -import { internalRuleToAPIResponse } from '../../../rule_management/normalization/rule_converters'; import { aggregatePrebuiltRuleErrors } from '../../logic/aggregate_prebuilt_rule_errors'; import { ensureLatestRulesPackageInstalled } from '../../logic/ensure_latest_rules_package_installed'; import { createPrebuiltRuleAssetsClient } from '../../logic/rule_assets/prebuilt_rule_assets_client'; @@ -135,7 +134,7 @@ export const performRuleInstallationRoute = (router: SecuritySolutionPluginRoute failed: ruleErrors.length, }, results: { - created: installedRules.map(({ result }) => internalRuleToAPIResponse(result)), + created: installedRules.map(({ result }) => result), skipped: skippedRules, }, errors: allErrors, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts index 8da1055156d3d..4f6d3b8314aa5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/rule_objects/create_prebuilt_rules.ts @@ -21,7 +21,7 @@ export const createPrebuiltRules = ( items: rules, executor: async (rule) => { return detectionRulesClient.createPrebuiltRule({ - ruleAsset: rule, + params: rule, }); }, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts index da0bc90c9e4df..cbc3e006a4fea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts @@ -10,6 +10,7 @@ import type { BulkError } from './utils'; import { transformBulkError, convertToSnakeCase, SiemResponseFactory } from './utils'; import { responseMock } from './__mocks__'; import { CustomHttpRequestError } from '../../../utils/custom_http_request_error'; +import { RuleResponseValidationError } from '../rule_management/logic/detection_rules_client/utils'; describe('utils', () => { describe('transformBulkError', () => { @@ -59,6 +60,24 @@ describe('utils', () => { }; expect(transformed).toEqual(expected); }); + + test('it detects a RuleResponseValidationError and returns an error status of 500', () => { + const error = new RuleResponseValidationError({ + ruleId: 'rule-1', + message: 'name: Required', + }); + + const expected: BulkError = { + rule_id: 'rule-1', + error: { message: 'name: Required', status_code: 500 }, + }; + + /* Works when the ruleId is passed in. For example, when creating a rule with a user-set ruleId */ + expect(transformBulkError('rule-1', error)).toEqual(expected); + + /* Works when the ruleId is not passed in. For example, when creating a rule with a generated ruleId */ + expect(transformBulkError(undefined, error)).toEqual(expected); + }); }); describe('convertToSnakeCase', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts index 5b0e859052500..0e08374b1f927 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts @@ -17,6 +17,7 @@ import type { } from '@kbn/core/server'; import { CustomHttpRequestError } from '../../../utils/custom_http_request_error'; +import { RuleResponseValidationError } from '../rule_management/logic/detection_rules_client/utils'; export interface OutputError { message: string; @@ -116,6 +117,12 @@ export const transformBulkError = ( statusCode: 400, message: err.message, }); + } else if (err instanceof RuleResponseValidationError) { + return createBulkErrorObject({ + ruleId: err.ruleId, + statusCode: 500, + message: err.message, + }); } else { return createBulkErrorObject({ ruleId, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.test.ts index 21ee4116edc2c..d6403f0d1553d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.test.ts @@ -22,6 +22,7 @@ import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-m import { getQueryRuleParams } from '../../../../rule_schema/mocks'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { HttpAuthzError } from '../../../../../machine_learning/validation'; +import { getRulesSchemaMock } from '../../../../../../../common/api/detection_engine/model/rule_schema/rule_response_schema.mock'; describe('Bulk create rules route', () => { let server: ReturnType; @@ -34,9 +35,7 @@ describe('Bulk create rules route', () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); // no existing rules clients.rulesClient.create.mockResolvedValue(getRuleMock(getQueryRuleParams())); // successful creation - clients.detectionRulesClient.createCustomRule.mockResolvedValue( - getRuleMock(getQueryRuleParams()) - ); + clients.detectionRulesClient.createCustomRule.mockResolvedValue(getRulesSchemaMock()); context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise(getBasicEmptySearchResponse()) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index a8e5a0446c6e3..ba6eebce2207c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -18,7 +18,6 @@ import { import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { getDuplicates } from './get_duplicates'; -import { transformValidateBulkError } from '../../../utils/validate'; import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { validateRuleDefaultExceptionList } from '../../../logic/exceptions/validate_rule_default_exception_list'; import { validateRulesWithDuplicatedDefaultExceptionsList } from '../../../logic/exceptions/validate_rules_with_duplicated_default_exceptions_list'; @@ -113,7 +112,7 @@ export const bulkCreateRulesRoute = (router: SecuritySolutionPluginRouter, logge params: payloadRule, }); - return transformValidateBulkError(createdRule.params.ruleId, createdRule); + return createdRule; } catch (err) { return transformBulkError( payloadRule.rule_id, @@ -122,6 +121,7 @@ export const bulkCreateRulesRoute = (router: SecuritySolutionPluginRouter, logge } }) ); + const rulesBulk = [ ...rules, ...dupes.map((ruleId) => diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.test.ts index 08a9f4e6c4769..1402518103e64 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.test.ts @@ -20,6 +20,7 @@ import { getCreateRulesSchemaMock } from '../../../../../../../common/api/detect import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { getQueryRuleParams } from '../../../../rule_schema/mocks'; import { HttpAuthzError } from '../../../../../machine_learning/validation'; +import { getRulesSchemaMock } from '../../../../../../../common/api/detection_engine/model/rule_schema/rule_response_schema.mock'; describe('Create rule route', () => { let server: ReturnType; @@ -31,9 +32,7 @@ describe('Create rule route', () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); // no current rules clients.rulesClient.create.mockResolvedValue(getRuleMock(getQueryRuleParams())); // creation succeeds - clients.detectionRulesClient.createCustomRule.mockResolvedValue( - getRuleMock(getQueryRuleParams()) - ); + clients.detectionRulesClient.createCustomRule.mockResolvedValue(getRulesSchemaMock()); context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise(getBasicEmptySearchResponse()) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts index 03642aa12266b..3819154c1b8a3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts @@ -19,7 +19,7 @@ import { buildSiemResponse } from '../../../../routes/utils'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { checkDefaultRuleExceptionListReferences } from '../../../logic/exceptions/check_for_default_rule_exception_list'; import { validateRuleDefaultExceptionList } from '../../../logic/exceptions/validate_rule_default_exception_list'; -import { transformValidate, validateResponseActionsPermissions } from '../../../utils/validate'; +import { validateResponseActionsPermissions } from '../../../utils/validate'; export const createRuleRoute = (router: SecuritySolutionPluginRouter): void => { router.versioned @@ -94,7 +94,7 @@ export const createRuleRoute = (router: SecuritySolutionPluginRouter): void => { }); return response.ok({ - body: transformValidate(createdRule), + body: createdRule, }); } catch (err) { const error = transformError(err as Error); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_custom_rule.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_custom_rule.test.ts index a8335108d7cbe..1cf4afecedb26 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_custom_rule.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_custom_rule.test.ts @@ -12,11 +12,15 @@ import { getCreateMachineLearningRulesSchemaMock, getCreateThreatMatchRulesSchemaMock, } from '../../../../../../common/api/detection_engine/model/rule_schema/mocks'; +import { getRuleMock } from '../../../routes/__mocks__/request_responses'; +import { getQueryRuleParams } from '../../../rule_schema/mocks'; import { DEFAULT_INDICATOR_SOURCE_PATH } from '../../../../../../common/constants'; import { buildMlAuthz } from '../../../../machine_learning/authz'; import { throwAuthzError } from '../../../../machine_learning/validation'; import { createDetectionRulesClient } from './detection_rules_client'; import type { IDetectionRulesClient } from './detection_rules_client_interface'; +import { RuleResponseValidationError } from './utils'; +import type { RuleAlertType } from '../../../rule_schema'; jest.mock('../../../../machine_learning/authz'); jest.mock('../../../../machine_learning/validation'); @@ -29,7 +33,10 @@ describe('DetectionRulesClient.createCustomRule', () => { beforeEach(() => { jest.resetAllMocks(); + rulesClient = rulesClientMock.create(); + rulesClient.create.mockResolvedValue(getRuleMock(getQueryRuleParams())); + detectionRulesClient = createDetectionRulesClient(rulesClient, mlAuthz); }); @@ -63,6 +70,20 @@ describe('DetectionRulesClient.createCustomRule', () => { expect(rulesClient.create).not.toHaveBeenCalled(); }); + it('throws if RuleResponse validation fails', async () => { + const internalRuleMock: RuleAlertType = getRuleMock({ + ...getQueryRuleParams(), + /* Casting as 'query' suppress to TS error */ + type: 'fake-non-existent-type' as 'query', + }); + + rulesClient.create.mockResolvedValueOnce(internalRuleMock); + + await expect( + detectionRulesClient.createCustomRule({ params: getCreateMachineLearningRulesSchemaMock() }) + ).rejects.toThrow(RuleResponseValidationError); + }); + it('calls the rulesClient with legacy ML params', async () => { await detectionRulesClient.createCustomRule({ params: getCreateMachineLearningRulesSchemaMock(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_prebuilt_rule.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_prebuilt_rule.test.ts index d2a61dcc65e45..fd3ac991a968f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_prebuilt_rule.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.create_prebuilt_rule.test.ts @@ -12,6 +12,8 @@ import { getCreateMachineLearningRulesSchemaMock, getCreateThreatMatchRulesSchemaMock, } from '../../../../../../common/api/detection_engine/model/rule_schema/mocks'; +import { getRuleMock } from '../../../routes/__mocks__/request_responses'; +import { getQueryRuleParams } from '../../../rule_schema/mocks'; import { DEFAULT_INDICATOR_SOURCE_PATH } from '../../../../../../common/constants'; import { buildMlAuthz } from '../../../../machine_learning/authz'; import { throwAuthzError } from '../../../../machine_learning/validation'; @@ -29,22 +31,25 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { beforeEach(() => { jest.resetAllMocks(); + rulesClient = rulesClientMock.create(); + rulesClient.create.mockResolvedValue(getRuleMock(getQueryRuleParams())); + detectionRulesClient = createDetectionRulesClient(rulesClient, mlAuthz); }); it('creates a rule with the correct parameters and options', async () => { - const ruleAsset = { ...getCreateRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; + const params = { ...getCreateRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; - await detectionRulesClient.createPrebuiltRule({ ruleAsset }); + await detectionRulesClient.createPrebuiltRule({ params }); expect(rulesClient.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ enabled: false, - name: ruleAsset.name, + name: params.name, params: expect.objectContaining({ - ruleId: ruleAsset.rule_id, + ruleId: params.rule_id, immutable: true, }), }), @@ -53,12 +58,12 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { }); it('throws if mlAuth fails', async () => { - const ruleAsset = { ...getCreateRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; + const params = { ...getCreateRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; (throwAuthzError as jest.Mock).mockImplementationOnce(() => { throw new Error('mocked MLAuth error'); }); - await expect(detectionRulesClient.createPrebuiltRule({ ruleAsset })).rejects.toThrow( + await expect(detectionRulesClient.createPrebuiltRule({ params })).rejects.toThrow( 'mocked MLAuth error' ); @@ -66,13 +71,13 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { }); it('calls the rulesClient with legacy ML params', async () => { - const ruleAsset = { + const params = { ...getCreateMachineLearningRulesSchemaMock(), version: 1, rule_id: 'rule-id', }; await detectionRulesClient.createPrebuiltRule({ - ruleAsset, + params, }); expect(rulesClient.create).toHaveBeenCalledWith( @@ -80,8 +85,8 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { data: expect.objectContaining({ enabled: false, params: expect.objectContaining({ - anomalyThreshold: ruleAsset.anomaly_threshold, - machineLearningJobId: [ruleAsset.machine_learning_job_id], + anomalyThreshold: params.anomaly_threshold, + machineLearningJobId: [params.machine_learning_job_id], immutable: true, }), }), @@ -90,14 +95,14 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { }); it('calls the rulesClient with ML params', async () => { - const ruleAsset = { + const params = { ...getCreateMachineLearningRulesSchemaMock(), machine_learning_job_id: ['new_job_1', 'new_job_2'], version: 1, rule_id: 'rule-id', }; await detectionRulesClient.createPrebuiltRule({ - ruleAsset, + params, }); expect(rulesClient.create).toHaveBeenCalledWith( @@ -115,11 +120,11 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { }); it('populates a threatIndicatorPath value for threat_match rule if empty', async () => { - const ruleAsset = { ...getCreateThreatMatchRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; - delete ruleAsset.threat_indicator_path; + const params = { ...getCreateThreatMatchRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; + delete params.threat_indicator_path; await detectionRulesClient.createPrebuiltRule({ - ruleAsset, + params, }); expect(rulesClient.create).toHaveBeenCalledWith( @@ -136,8 +141,8 @@ describe('DetectionRulesClient.createPrebuiltRule', () => { }); it('does not populate a threatIndicatorPath value for other rules if empty', async () => { - const ruleAsset = { ...getCreateRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; - await detectionRulesClient.createPrebuiltRule({ ruleAsset }); + const params = { ...getCreateRulesSchemaMock(), version: 1, rule_id: 'rule-id' }; + await detectionRulesClient.createPrebuiltRule({ params }); expect(rulesClient.create).not.toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.ts index 7256441697e65..c26649604b282 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client.ts @@ -9,6 +9,7 @@ import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { MlAuthz } from '../../../../machine_learning/authz'; import type { RuleAlertType } from '../../../rule_schema'; +import type { RuleResponse } from '../../../../../../common/api/detection_engine/model/rule_schema'; import type { IDetectionRulesClient, CreateCustomRuleArgs, @@ -34,13 +35,13 @@ export const createDetectionRulesClient = ( rulesClient: RulesClient, mlAuthz: MlAuthz ): IDetectionRulesClient => ({ - async createCustomRule(args: CreateCustomRuleArgs): Promise { + async createCustomRule(args: CreateCustomRuleArgs): Promise { return withSecuritySpan('DetectionRulesClient.createCustomRule', async () => { return createCustomRule(rulesClient, args, mlAuthz); }); }, - async createPrebuiltRule(args: CreatePrebuiltRuleArgs): Promise { + async createPrebuiltRule(args: CreatePrebuiltRuleArgs): Promise { return withSecuritySpan('DetectionRulesClient.createPrebuiltRule', async () => { return createPrebuiltRule(rulesClient, args, mlAuthz); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client_interface.ts index d99b0b9c2cbd0..2d9c787119cdf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/detection_rules_client_interface.ts @@ -5,26 +5,25 @@ * 2.0. */ -import type { RuleCreateProps } from '../../../../../../common/api/detection_engine/model/rule_schema'; -import type { PrebuiltRuleAsset } from '../../../prebuilt_rules'; import type { + RuleCreateProps, RuleUpdateProps, RulePatchProps, RuleObjectId, RuleToImport, + RuleResponse, } from '../../../../../../common/api/detection_engine'; import type { RuleAlertType } from '../../../rule_schema'; +import type { PrebuiltRuleAsset } from '../../../prebuilt_rules'; export interface IDetectionRulesClient { - createCustomRule: (createCustomRulePayload: CreateCustomRuleArgs) => Promise; - createPrebuiltRule: (createPrebuiltRulePayload: CreatePrebuiltRuleArgs) => Promise; - updateRule: (updateRulePayload: UpdateRuleArgs) => Promise; - patchRule: (patchRulePayload: PatchRuleArgs) => Promise; - deleteRule: (deleteRulePayload: DeleteRuleArgs) => Promise; - upgradePrebuiltRule: ( - upgradePrebuiltRulePayload: UpgradePrebuiltRuleArgs - ) => Promise; - importRule: (importRulePayload: ImportRuleArgs) => Promise; + createCustomRule: (args: CreateCustomRuleArgs) => Promise; + createPrebuiltRule: (args: CreatePrebuiltRuleArgs) => Promise; + updateRule: (args: UpdateRuleArgs) => Promise; + patchRule: (args: PatchRuleArgs) => Promise; + deleteRule: (args: DeleteRuleArgs) => Promise; + upgradePrebuiltRule: (args: UpgradePrebuiltRuleArgs) => Promise; + importRule: (args: ImportRuleArgs) => Promise; } export interface CreateCustomRuleArgs { @@ -32,7 +31,7 @@ export interface CreateCustomRuleArgs { } export interface CreatePrebuiltRuleArgs { - ruleAsset: PrebuiltRuleAsset; + params: RuleCreateProps; } export interface UpdateRuleArgs { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_custom_rule.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_custom_rule.ts index c9b3b7b542a17..c77446f5baf63 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_custom_rule.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_custom_rule.ts @@ -6,18 +6,20 @@ */ import type { RulesClient } from '@kbn/alerting-plugin/server'; +import { stringifyZodError } from '@kbn/zod-helpers'; import type { CreateCustomRuleArgs } from '../detection_rules_client_interface'; import type { MlAuthz } from '../../../../../machine_learning/authz'; -import type { RuleAlertType, RuleParams } from '../../../../rule_schema'; +import type { RuleParams } from '../../../../rule_schema'; +import { RuleResponse } from '../../../../../../../common/api/detection_engine/model/rule_schema'; import { convertCreateAPIToInternalSchema } from '../../../normalization/rule_converters'; - -import { validateMlAuth } from '../utils'; +import { transform } from '../../../utils/utils'; +import { validateMlAuth, RuleResponseValidationError } from '../utils'; export const createCustomRule = async ( rulesClient: RulesClient, args: CreateCustomRuleArgs, mlAuthz: MlAuthz -): Promise => { +): Promise => { const { params } = args; await validateMlAuth(mlAuthz, params.type); @@ -26,5 +28,15 @@ export const createCustomRule = async ( data: internalRule, }); - return rule; + /* Trying to convert the rule to a RuleResponse object */ + const parseResult = RuleResponse.safeParse(transform(rule)); + + if (!parseResult.success) { + throw new RuleResponseValidationError({ + message: stringifyZodError(parseResult.error), + ruleId: rule.params.ruleId, + }); + } + + return parseResult.data; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_prebuilt_rule.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_prebuilt_rule.ts index 0ada0197137a4..db510d9071c4f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_prebuilt_rule.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/methods/create_prebuilt_rule.ts @@ -6,23 +6,25 @@ */ import type { RulesClient } from '@kbn/alerting-plugin/server'; +import { stringifyZodError } from '@kbn/zod-helpers'; import type { CreatePrebuiltRuleArgs } from '../detection_rules_client_interface'; import type { MlAuthz } from '../../../../../machine_learning/authz'; -import type { RuleAlertType, RuleParams } from '../../../../rule_schema'; +import { RuleResponse } from '../../../../../../../common/api/detection_engine/model/rule_schema'; +import type { RuleParams } from '../../../../rule_schema'; import { convertCreateAPIToInternalSchema } from '../../../normalization/rule_converters'; - -import { validateMlAuth } from '../utils'; +import { transform } from '../../../utils/utils'; +import { validateMlAuth, RuleResponseValidationError } from '../utils'; export const createPrebuiltRule = async ( rulesClient: RulesClient, args: CreatePrebuiltRuleArgs, mlAuthz: MlAuthz -): Promise => { - const { ruleAsset } = args; +): Promise => { + const { params } = args; - await validateMlAuth(mlAuthz, ruleAsset.type); + await validateMlAuth(mlAuthz, params.type); - const internalRule = convertCreateAPIToInternalSchema(ruleAsset, { + const internalRule = convertCreateAPIToInternalSchema(params, { immutable: true, defaultEnabled: false, }); @@ -31,5 +33,15 @@ export const createPrebuiltRule = async ( data: internalRule, }); - return rule; + /* Trying to convert the rule to a RuleResponse object */ + const parseResult = RuleResponse.safeParse(transform(rule)); + + if (!parseResult.success) { + throw new RuleResponseValidationError({ + message: stringifyZodError(parseResult.error), + ruleId: rule.params.ruleId, + }); + } + + return parseResult.data; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/utils.ts index 0173ba5aea370..624f86a49422a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/utils.ts @@ -5,12 +5,15 @@ * 2.0. */ +/* eslint-disable max-classes-per-file */ + import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { Type } from '@kbn/securitysolution-io-ts-alerting-types'; import type { MlAuthz } from '../../../../machine_learning/authz'; import type { RuleAlertType } from '../../../rule_schema'; +import type { RuleSignatureId } from '../../../../../../common/api/detection_engine/model/rule_schema/common_attributes.gen'; import { throwAuthzError } from '../../../../machine_learning/validation'; export const toggleRuleEnabledOnUpdate = async ( @@ -36,3 +39,19 @@ export class ClientError extends Error { this.statusCode = statusCode; } } + +/** + * Represents an error that occurred while validating a RuleResponse object. + * Includes the ruleId (rule signature id) of the rule that failed validation. + * Thrown when a rule does not match the RuleResponse schema. + * @param message - The error message + * @param ruleId - The rule signature id of the rule that failed validation + * @extends Error + */ +export class RuleResponseValidationError extends Error { + public readonly ruleId: RuleSignatureId; + constructor({ message, ruleId }: { message: string; ruleId: RuleSignatureId }) { + super(message); + this.ruleId = ruleId; + } +} From a0fb706e31d7a38d1a404040b5d7f2ccb4e60b11 Mon Sep 17 00:00:00 2001 From: Alexi Doak <109488926+doakalexi@users.noreply.github.com> Date: Tue, 18 Jun 2024 07:44:36 -0700 Subject: [PATCH 055/127] [ResponseOps] ES|QL rule type improvements - write query results to the alert doc (#184541) Resolves https://github.com/elastic/response-ops-team/issues/200 ## Summary This PR copies the fields from the ES|QL query results to the alert doc. Now that we are writing everything to the alert doc I removed the source fields selector from the ES|QL ui. ### Checklist - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### To verify - Create an ES Query ES|QL rule. - Go to [dev tools](http://localhost:5601/app/dev_tools#/console) and run the query below to verify that the query results are written to the alert doc. ``` GET .internal.alerts-stack.alerts-default*/_search ``` --- .../src/schemas/generated/stack_schema.ts | 3 +- .../public/rule_types/es_query/constants.ts | 1 - .../expression/esql_query_expression.tsx | 53 +++---------------- .../server/rule_types/constants.ts | 1 + .../es_query/lib/fetch_esql_query.test.ts | 28 +++++++++- .../es_query/lib/fetch_esql_query.ts | 22 +++++++- .../lib/parse_aggregation_results.test.ts | 6 +-- .../data/lib/parse_aggregation_results.ts | 4 +- .../builtin_alert_types/es_query/esql_only.ts | 14 +---- .../apis/maps/maps_telemetry.ts | 4 +- 10 files changed, 65 insertions(+), 71 deletions(-) diff --git a/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts b/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts index 94ba544e4c96f..1d85ffcb1f714 100644 --- a/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts +++ b/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts @@ -11,6 +11,7 @@ import * as rt from 'io-ts'; import { Either } from 'fp-ts/lib/Either'; import { AlertSchema } from './alert_schema'; +import { EcsSchema } from './ecs_schema'; const ISO_DATE_PATTERN = /^d{4}-d{2}-d{2}Td{2}:d{2}:d{2}.d{3}Z$/; export const IsoDateString = new rt.Type( 'IsoDateString', @@ -77,6 +78,6 @@ const StackAlertOptional = rt.partial({ }); // prettier-ignore -export const StackAlertSchema = rt.intersection([StackAlertRequired, StackAlertOptional, AlertSchema]); +export const StackAlertSchema = rt.intersection([StackAlertRequired, StackAlertOptional, AlertSchema, EcsSchema]); // prettier-ignore export type StackAlert = rt.TypeOf; diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/constants.ts b/x-pack/plugins/stack_alerts/public/rule_types/es_query/constants.ts index 7d01043bfbc21..e40f373cb95fc 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/constants.ts +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/constants.ts @@ -22,7 +22,6 @@ export const DEFAULT_VALUES = { GROUP_BY: 'all', EXCLUDE_PREVIOUS_HITS: false, CAN_SELECT_MULTI_TERMS: true, - SOURCE_FIELDS: [], }; export const SERVERLESS_DEFAULT_VALUES = { SIZE: 10, diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx index febae77ad0f22..3ff2b70522e9a 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/esql_query_expression.tsx @@ -6,7 +6,7 @@ */ import React, { useState, Fragment, useEffect, useCallback } from 'react'; -import { debounce, get } from 'lodash'; +import { get } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiFieldNumber, @@ -16,7 +16,6 @@ import { EuiSelect, EuiSpacer, } from '@elastic/eui'; -import { getESQLQueryColumns } from '@kbn/esql-utils'; import { getFields, RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; import { TextBasedLangEditor } from '@kbn/text-based-languages/public'; import { fetchFieldsFromESQL } from '@kbn/text-based-editor'; @@ -24,14 +23,12 @@ import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; import type { AggregateQuery } from '@kbn/es-query'; import { parseDuration } from '@kbn/alerting-plugin/common'; import { - FieldOption, firstFieldOption, getTimeFieldOptions, getTimeOptions, parseAggregationResults, } from '@kbn/triggers-actions-ui-plugin/public/common'; import { DataView } from '@kbn/data-views-plugin/common'; -import { SourceFields } from '../../components/source_fields_select'; import { EsQueryRuleParams, EsQueryRuleMetaData, SearchType } from '../types'; import { DEFAULT_VALUES, SERVERLESS_DEFAULT_VALUES } from '../constants'; import { useTriggerUiActionServices } from '../util'; @@ -42,8 +39,8 @@ import { rowToDocument, toEsQueryHits, transformDatatableToEsqlTable } from '../ export const EsqlQueryExpression: React.FC< RuleTypeParamsExpressionProps, EsQueryRuleMetaData> > = ({ ruleParams, setRuleParams, setRuleProperty, errors }) => { - const { expressions, http, fieldFormats, isServerless, data } = useTriggerUiActionServices(); - const { esqlQuery, timeWindowSize, timeWindowUnit, timeField, sourceFields } = ruleParams; + const { expressions, http, fieldFormats, isServerless } = useTriggerUiActionServices(); + const { esqlQuery, timeWindowSize, timeWindowUnit, timeField } = ruleParams; const [currentRuleParams, setCurrentRuleParams] = useState< EsQueryRuleParams @@ -61,12 +58,12 @@ export const EsqlQueryExpression: React.FC< groupBy: DEFAULT_VALUES.GROUP_BY, termSize: DEFAULT_VALUES.TERM_SIZE, searchType: SearchType.esqlQuery, - sourceFields: sourceFields ?? DEFAULT_VALUES.SOURCE_FIELDS, + // The sourceFields param is ignored for the ES|QL type + sourceFields: [], }); const [query, setQuery] = useState({ esql: '' }); const [timeFieldOptions, setTimeFieldOptions] = useState([firstFieldOption]); const [detectTimestamp, setDetectTimestamp] = useState(false); - const [esFields, setEsFields] = useState([]); const [isLoading, setIsLoading] = useState(false); const setParam = useCallback( @@ -86,7 +83,6 @@ export const EsqlQueryExpression: React.FC< if (esqlQuery) { if (esqlQuery.esql) { refreshTimeFields(esqlQuery); - refreshEsFields(esqlQuery, false); } } if (timeField) { @@ -180,32 +176,6 @@ export const EsqlQueryExpression: React.FC< setDetectTimestamp(hasTimestamp); }; - const refreshEsFields = async (q: AggregateQuery, resetSourceFields: boolean = true) => { - let fields: FieldOption[] = []; - try { - const columns = await getESQLQueryColumns({ - esqlQuery: `${get(q, 'esql')}`, - search: data.search.search, - }); - if (columns.length) { - fields = columns.map((c) => ({ - name: c.id, - type: c.meta.type, - normalizedType: c.meta.type, - searchable: true, - aggregatable: true, - })); - } - } catch (error) { - /** ignore error */ - } - - if (resetSourceFields) { - setParam('sourceFields', undefined); - } - setEsFields(fields); - }; - return ( { + onTextLangQueryChange={(q: AggregateQuery) => { setQuery(q); setParam('esqlQuery', q); refreshTimeFields(q); - refreshEsFields(q); - }, 1000)} + }} expandCodeEditor={() => true} isCodeEditorExpanded={true} onTextLangQuerySubmit={async () => {}} @@ -236,14 +205,6 @@ export const EsqlQueryExpression: React.FC< isLoading={isLoading} /> - - setParam('sourceFields', selectedSourceFields) - } - esFields={esFields} - sourceFields={sourceFields} - errors={errors.sourceFields} - /> = { }, }, shouldWrite: true, + useEcs: true, }; diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.test.ts index 1d7096d20140e..b23cddc0eaab7 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.test.ts @@ -7,7 +7,7 @@ import { OnlyEsqlQueryRuleParams } from '../types'; import { Comparator } from '../../../../common/comparator_types'; -import { getEsqlQuery } from './fetch_esql_query'; +import { getEsqlQuery, getSourceFields } from './fetch_esql_query'; const getTimeRange = () => { const date = Date.now(); @@ -98,4 +98,30 @@ describe('fetchEsqlQuery', () => { `); }); }); + + describe('getSourceFields', () => { + it('should generate the correct source fields', async () => { + const sourceFields = getSourceFields({ + columns: [ + { name: '@timestamp', type: 'date' }, + { name: 'ecs.version', type: 'keyword' }, + { name: 'error.code', type: 'keyword' }, + ], + values: [['2023-07-12T13:32:04.174Z', '1.8.0', null]], + }); + + expect(sourceFields).toMatchInlineSnapshot(` + Array [ + Object { + "label": "ecs.version", + "searchPath": "ecs.version", + }, + Object { + "label": "error.code", + "searchPath": "error.code", + }, + ] + `); + }); + }); }); diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.ts index 87ae2c1123547..5ecb258b0579f 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_esql_query.ts @@ -5,9 +5,11 @@ * 2.0. */ +import { intersectionBy } from 'lodash'; import { parseAggregationResults } from '@kbn/triggers-actions-ui-plugin/common'; import { SharePluginStart } from '@kbn/share-plugin/server'; import { IScopedClusterClient, Logger } from '@kbn/core/server'; +import { ecsFieldMap, alertFieldMap } from '@kbn/alerts-as-data-utils'; import { OnlyEsqlQueryRuleParams } from '../types'; import { EsqlTable, toEsQueryHits } from '../../../../common'; @@ -47,6 +49,8 @@ export async function fetchEsqlQuery({ path: '/_query', body: query, }); + const hits = toEsQueryHits(response); + const sourceFields = getSourceFields(response); const link = `${publicBaseUrl}${spacePrefix}/app/management/insightsAndAlerting/triggersActions/rule/${ruleId}`; @@ -60,10 +64,10 @@ export async function fetchEsqlQuery({ took: 0, timed_out: false, _shards: { failed: 0, successful: 0, total: 0 }, - hits: toEsQueryHits(response), + hits, }, resultLimit: alertLimit, - sourceFieldsParams: params.sourceFields, + sourceFieldsParams: sourceFields, generateSourceFieldsFromHits: true, }), index: null, @@ -98,3 +102,17 @@ export const getEsqlQuery = ( }; return query; }; + +export const getSourceFields = (results: EsqlTable) => { + const resultFields = results.columns.map((c) => ({ + label: c.name, + searchPath: c.name, + })); + const alertFields = Object.keys(alertFieldMap); + const ecsFields = Object.keys(ecsFieldMap) + // exclude the alert fields that we don't want to override + .filter((key) => !alertFields.includes(key)) + .map((key) => ({ label: key, searchPath: key })); + + return intersectionBy(resultFields, ecsFields, 'label'); +}; diff --git a/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.test.ts b/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.test.ts index e22d4959c6093..b881aa7609954 100644 --- a/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.test.ts +++ b/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.test.ts @@ -843,9 +843,9 @@ describe('parseAggregationResults', () => { sampleEsqlSourceFieldsHit, ], sourceFields: { - 'host.hostname': ['host-1'], - 'host.id': ['1'], - 'host.name': ['host-1'], + 'host.hostname': ['host-1', 'host-1', 'host-1', 'host-1'], + 'host.id': ['1', '1', '1', '1'], + 'host.name': ['host-1', 'host-1', 'host-1', 'host-1'], }, }, ], diff --git a/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts b/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts index 6fe7040abacc3..756f79dceec97 100644 --- a/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts +++ b/x-pack/plugins/triggers_actions_ui/common/data/lib/parse_aggregation_results.ts @@ -87,10 +87,10 @@ export const parseAggregationResults = ({ sourceFieldsParams.forEach((field) => { if (generateSourceFieldsFromHits) { - const fieldsSet = new Set(); + const fieldsSet: string[] = []; groupBucket.topHitsAgg.hits.hits.forEach((hit: SearchHit<{ [key: string]: string }>) => { if (hit._source && hit._source[field.label]) { - fieldsSet.add(hit._source[field.label]); + fieldsSet.push(hit._source[field.label]); } }); sourceFields[field.label] = Array.from(fieldsSet); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts index f193af1b81703..56934c5d5f8a3 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts @@ -22,7 +22,6 @@ import { RULE_INTERVAL_MILLIS, RULE_INTERVAL_SECONDS, RULE_TYPE_ID, - SourceField, } from './common'; import { createDataStream, deleteDataStream } from '../../../create_test_data'; @@ -39,12 +38,6 @@ export default function ruleTests({ getService }: FtrProviderContext) { getAllAADDocs, } = getRuleServices(getService); - const sourceFields = [ - { label: 'host.hostname', searchPath: 'host.hostname.keyword' }, - { label: 'host.id', searchPath: 'host.id' }, - { label: 'host.name', searchPath: 'host.name' }, - ]; - describe('rule', async () => { let endDate: string; let connectorId: string; @@ -81,13 +74,11 @@ export default function ruleTests({ getService }: FtrProviderContext) { name: 'never fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) by host.hostname, host.name, host.id | where c < 0', - sourceFields, }); await createRule({ name: 'always fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) by host.hostname, host.name, host.id | where c > -1', - sourceFields, }); const docs = await waitForDocs(2); @@ -225,13 +216,11 @@ export default function ruleTests({ getService }: FtrProviderContext) { name: 'never fire', esqlQuery: 'from test-data-stream | stats c = count(@timestamp) by host.hostname, host.name, host.id | where c < 0', - sourceFields, }); await createRule({ name: 'always fire', esqlQuery: 'from test-data-stream | stats c = count(@timestamp) by host.hostname, host.name, host.id | where c > -1', - sourceFields, }); const messagePattern = /Document count is \d+ in the last 20s. Alert when greater than 0./; @@ -397,7 +386,6 @@ export default function ruleTests({ getService }: FtrProviderContext) { groupBy?: string; termField?: string; termSize?: number; - sourceFields?: SourceField[]; } async function createRule(params: CreateRuleParams): Promise { @@ -469,7 +457,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { termSize: params.termSize, timeField: params.timeField || 'date', esqlQuery: { esql: params.esqlQuery }, - sourceFields: params.sourceFields, + sourceFields: [], }, }) .expect(200); diff --git a/x-pack/test/api_integration/apis/maps/maps_telemetry.ts b/x-pack/test/api_integration/apis/maps/maps_telemetry.ts index 8f5c9ae95f8af..acd846f77c982 100644 --- a/x-pack/test/api_integration/apis/maps/maps_telemetry.ts +++ b/x-pack/test/api_integration/apis/maps/maps_telemetry.ts @@ -36,8 +36,8 @@ export default function ({ getService }: FtrProviderContext) { return fieldStat.name === 'geo_point'; } ); - expect(geoPointFieldStats.count).to.be(39); - expect(geoPointFieldStats.index_count).to.be(10); + expect(geoPointFieldStats.count).to.be(47); + expect(geoPointFieldStats.index_count).to.be(11); const geoShapeFieldStats = apiResponse.cluster_stats.indices.mappings.field_types.find( (fieldStat: estypes.ClusterStatsFieldTypes) => { From b810572ca0d744e3d024bf20598467f24c398201 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 18 Jun 2024 15:53:43 +0100 Subject: [PATCH 056/127] [ML] Refresh jobs list after import (#184757) Fixes https://github.com/elastic/kibana/issues/184063 Adds a callback prop to allow the import flyout to refresh the jobs list after importing jobs or synchronising saved objects. --- .../import_jobs_flyout/import_jobs_flyout.tsx | 6 +++++- .../components/jobs_list_page/jobs_list_page.tsx | 13 +++++++++++-- .../space_management/space_management.tsx | 14 +++++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/import_export_jobs/import_jobs_flyout/import_jobs_flyout.tsx b/x-pack/plugins/ml/public/application/components/import_export_jobs/import_jobs_flyout/import_jobs_flyout.tsx index e98881f1e56d8..d0870466aa89a 100644 --- a/x-pack/plugins/ml/public/application/components/import_export_jobs/import_jobs_flyout/import_jobs_flyout.tsx +++ b/x-pack/plugins/ml/public/application/components/import_export_jobs/import_jobs_flyout/import_jobs_flyout.tsx @@ -45,9 +45,10 @@ import { useEnabledFeatures } from '../../../contexts/ml'; export interface Props { isDisabled: boolean; + onImportComplete: (() => void) | null; } -export const ImportJobsFlyout: FC = ({ isDisabled }) => { +export const ImportJobsFlyout: FC = ({ isDisabled, onImportComplete }) => { const { services: { data: { @@ -204,6 +205,9 @@ export const ImportJobsFlyout: FC = ({ isDisabled }) => { setImporting(false); setShowFlyout(false); + if (typeof onImportComplete === 'function') { + onImportComplete(); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [jobType, jobIdObjects, adJobs, dfaJobs]); diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx index 39b9520876fb0..ca0617bedc1c7 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx @@ -74,6 +74,8 @@ export const JobsListPage: FC = ({ const [isPlatinumOrTrialLicense, setIsPlatinumOrTrialLicense] = useState(true); const [showSyncFlyout, setShowSyncFlyout] = useState(false); const [currentTabId, setCurrentTabId] = useState('anomaly-detector'); + // callback to allow import flyout to refresh jobs list + const [refreshJobs, setRefreshJobs] = useState<(() => void) | null>(null); const mlServices = useMemo( () => getMlGlobalServices(coreStart.http, data.dataViews, usageCollection), @@ -109,6 +111,9 @@ export const JobsListPage: FC = ({ } function onCloseSyncFlyout() { + if (typeof refreshJobs === 'function') { + refreshJobs(); + } setShowSyncFlyout(false); } @@ -203,10 +208,14 @@ export const JobsListPage: FC = ({ /> - + - + diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/space_management/space_management.tsx b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/space_management/space_management.tsx index fd65469f884d5..76c3293f97061 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/space_management/space_management.tsx +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/space_management/space_management.tsx @@ -34,10 +34,11 @@ import { getFilters } from './filters'; interface Props { spacesApi?: SpacesPluginStart; - setCurrentTab: (tabId: MlSavedObjectType) => void; + onTabChange: (tabId: MlSavedObjectType) => void; + onReload: React.Dispatch void) | null>>; } -export const SpaceManagement: FC = ({ spacesApi, setCurrentTab }) => { +export const SpaceManagement: FC = ({ spacesApi, onTabChange, onReload }) => { const { getList } = useManagementApiService(); const [currentTabId, setCurrentTabId] = useState(null); @@ -101,12 +102,19 @@ export const SpaceManagement: FC = ({ spacesApi, setCurrentTab }) => { [getList, loadingTab] ); + useEffect(() => { + onReload(() => () => refresh(currentTabId)); + return () => { + onReload(null); + }; + }, [currentTabId, refresh, onReload]); + useEffect( function refreshOnTabChange() { setItems(undefined); if (currentTabId !== null) { setColumns(createColumns()); - setCurrentTab(currentTabId); + onTabChange(currentTabId); refresh(currentTabId); setPageIndex(0); } From bee8973c51955944026c3be9513410b7e0cb282c Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 18 Jun 2024 08:07:48 -0700 Subject: [PATCH 057/127] [DOCS] Deprecate old advanced settings (#186309) --- docs/management/advanced-options.asciidoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index bad18a706cbf2..98886aedd5535 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -310,6 +310,7 @@ Limits the number of rows per page in the document table. Sets the maximum number of rows for the entire document table. This is the maximum number of documents fetched from {es}. [[discover-searchFieldsFromSource]]`discover:searchFieldsFromSource`:: +deprecated:[8.15.0] Load fields from the original JSON {ref}/mapping-source-field.html[`_source`]. When disabled, *Discover* loads fields using the {es} search API's {ref}/search-fields.html#search-fields-param[`fields`] parameter. @@ -339,7 +340,7 @@ Highlights results in *Discover* and saved searches on dashboards. Highlighting slows requests when working on big documents. [[doctable-legacy]]`doc_table:legacy`:: -Controls the way the document table looks and works. +deprecated:[8.15.0] Controls the way the document table looks and works. To use the new *Document Explorer* instead of the classic view, turn off this option. The *Document Explorer* offers better data sorting, resizable columns, and a full screen view. @@ -512,7 +513,7 @@ deprecated::[8.11.0,'Rollups are deprecated and will be removed in a future vers [horizontal] [[rollups-enableindexpatterns]]`rollups:enableIndexPatterns`:: -Enables the creation of data views that capture rollup indices, which in +deprecated:[8.15.0] Enables the creation of data views that capture rollup indices, which in turn enables visualizations based on rollup data. Refresh the page to apply the changes. From 67933dcb470049ea89998718ea450df85828e876 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 18 Jun 2024 17:43:04 +0200 Subject: [PATCH 058/127] [OAS] Deprecations (#186062) ## Summary Adds support for the [`deprecated` field](https://swagger.io/specification/) at the operation level to our router conversion logic. Close https://github.com/elastic/kibana/issues/186003 --- .../src/router.test.ts | 15 ++++++++++++++- .../core_versioned_router.test.ts | 12 ++++++++++-- .../http/core-http-server/src/router/route.ts | 8 ++++++++ .../http/core-http-server/src/versioning/types.ts | 10 +++++++++- .../src/__snapshots__/generate_oas.test.ts.snap | 6 +----- .../src/generate_oas.test.util.ts | 1 + .../src/process_router.ts | 3 ++- .../src/process_versioned_router.ts | 3 ++- 8 files changed, 47 insertions(+), 11 deletions(-) diff --git a/packages/core/http/core-http-router-server-internal/src/router.test.ts b/packages/core/http/core-http-router-server-internal/src/router.test.ts index cab011a5f0f72..c9d9c28a88823 100644 --- a/packages/core/http/core-http-router-server-internal/src/router.test.ts +++ b/packages/core/http/core-http-router-server-internal/src/router.test.ts @@ -43,7 +43,15 @@ describe('Router', () => { const router = new Router('', logger, enhanceWithContext, routerOptions); const validation = schema.object({ foo: schema.string() }); router.post( - { path: '/', validate: { body: validation, query: validation, params: validation } }, + { + path: '/', + validate: { body: validation, query: validation, params: validation }, + options: { + deprecated: true, + summary: 'post test summary', + description: 'post test description', + }, + }, (context, req, res) => res.ok() ); const routes = router.getRoutes(); @@ -55,6 +63,11 @@ describe('Router', () => { path: '/', validationSchemas: { body: validation, query: validation, params: validation }, isVersioned: false, + options: { + deprecated: true, + summary: 'post test summary', + description: 'post test description', + }, }); }); diff --git a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.test.ts b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.test.ts index 8b5a7d23fa0ee..c29a3edd967af 100644 --- a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.test.ts +++ b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.test.ts @@ -32,8 +32,13 @@ describe('Versioned router', () => { it('provides the expected metadata', () => { const versionedRouter = CoreVersionedRouter.from({ router }); - versionedRouter.get({ path: '/test/{id}', access: 'internal' }); - versionedRouter.post({ path: '/test', access: 'internal' }); + versionedRouter.get({ path: '/test/{id}', access: 'internal', deprecated: true }); + versionedRouter.post({ + path: '/test', + access: 'internal', + summary: 'Post test', + description: 'Post test description', + }); versionedRouter.delete({ path: '/test', access: 'internal' }); expect(versionedRouter.getRoutes()).toMatchInlineSnapshot(` Array [ @@ -42,6 +47,7 @@ describe('Versioned router', () => { "method": "get", "options": Object { "access": "internal", + "deprecated": true, }, "path": "/test/{id}", }, @@ -50,6 +56,8 @@ describe('Versioned router', () => { "method": "post", "options": Object { "access": "internal", + "description": "Post test description", + "summary": "Post test", }, "path": "/test", }, diff --git a/packages/core/http/core-http-server/src/router/route.ts b/packages/core/http/core-http-server/src/router/route.ts index 983c495a1b541..aa5b8598e0d0b 100644 --- a/packages/core/http/core-http-server/src/router/route.ts +++ b/packages/core/http/core-http-server/src/router/route.ts @@ -198,6 +198,14 @@ export interface RouteConfigOptions { * ``` */ description?: string; + + /** + * Setting this to `true` declares this route to be deprecated. Consumers SHOULD + * refrain from usage of this route. + * + * @remarks This will be surfaced in OAS documentation. + */ + deprecated?: boolean; } /** diff --git a/packages/core/http/core-http-server/src/versioning/types.ts b/packages/core/http/core-http-server/src/versioning/types.ts index af3173691415f..5c4eb459196cc 100644 --- a/packages/core/http/core-http-server/src/versioning/types.ts +++ b/packages/core/http/core-http-server/src/versioning/types.ts @@ -32,7 +32,7 @@ export type VersionedRouteConfig = Omit< RouteConfig, 'validate' | 'options' > & { - options?: Omit, 'access' | 'description'>; + options?: Omit, 'access' | 'description' | 'deprecated'>; /** See {@link RouteConfigOptions['access']} */ access: Exclude['access'], undefined>; /** @@ -82,6 +82,14 @@ export type VersionedRouteConfig = Omit< * ``` */ description?: string; + + /** + * Declares this operation to be deprecated. Consumers SHOULD refrain from usage + * of this route. This will be surfaced in OAS documentation. + * + * @default false + */ + deprecated?: boolean; }; /** diff --git a/packages/kbn-router-to-openapispec/src/__snapshots__/generate_oas.test.ts.snap b/packages/kbn-router-to-openapispec/src/__snapshots__/generate_oas.test.ts.snap index fee1a8534a7ec..be1b698f5cd9a 100644 --- a/packages/kbn-router-to-openapispec/src/__snapshots__/generate_oas.test.ts.snap +++ b/packages/kbn-router-to-openapispec/src/__snapshots__/generate_oas.test.ts.snap @@ -26,7 +26,6 @@ Object { "paths": Object { "/foo/{id}": Object { "get": Object { - "description": undefined, "operationId": "/foo/{id}#0", "parameters": Array [ Object { @@ -133,7 +132,7 @@ Object { "paths": Object { "/bar": Object { "get": Object { - "description": undefined, + "deprecated": true, "operationId": "/bar#0", "parameters": Array [ Object { @@ -577,7 +576,6 @@ Object { "paths": Object { "/recursive": Object { "get": Object { - "description": undefined, "operationId": "/recursive#0", "parameters": Array [ Object { @@ -660,7 +658,6 @@ Object { "paths": Object { "/foo/{id}": Object { "get": Object { - "description": undefined, "operationId": "/foo/{id}#0", "parameters": Array [ Object { @@ -698,7 +695,6 @@ Object { }, "/test": Object { "get": Object { - "description": undefined, "operationId": "/test#0", "parameters": Array [ Object { diff --git a/packages/kbn-router-to-openapispec/src/generate_oas.test.util.ts b/packages/kbn-router-to-openapispec/src/generate_oas.test.util.ts index bed7d10c51d8e..2fb821018dcee 100644 --- a/packages/kbn-router-to-openapispec/src/generate_oas.test.util.ts +++ b/packages/kbn-router-to-openapispec/src/generate_oas.test.util.ts @@ -85,6 +85,7 @@ export const getVersionedRouterDefaults = () => ({ options: { summary: 'versioned route', access: 'public', + deprecated: true, options: { tags: ['ignore-me', 'oas-tag:versioned'], }, diff --git a/packages/kbn-router-to-openapispec/src/process_router.ts b/packages/kbn-router-to-openapispec/src/process_router.ts index 393b745b6aab3..9437612211a92 100644 --- a/packages/kbn-router-to-openapispec/src/process_router.ts +++ b/packages/kbn-router-to-openapispec/src/process_router.ts @@ -61,8 +61,9 @@ export const processRouter = ( const operation: OpenAPIV3.OperationObject = { summary: route.options.summary ?? '', - description: route.options.description, tags: route.options.tags ? extractTags(route.options.tags) : [], + ...(route.options.description ? { description: route.options.description } : {}), + ...(route.options.deprecated ? { deprecated: route.options.deprecated } : {}), requestBody: !!validationSchemas?.body ? { content: { diff --git a/packages/kbn-router-to-openapispec/src/process_versioned_router.ts b/packages/kbn-router-to-openapispec/src/process_versioned_router.ts index cc873b26835cf..19b41f4812a30 100644 --- a/packages/kbn-router-to-openapispec/src/process_versioned_router.ts +++ b/packages/kbn-router-to-openapispec/src/process_versioned_router.ts @@ -85,8 +85,9 @@ export const processVersionedRouter = ( const hasVersionFilter = Boolean(filters?.version); const operation: OpenAPIV3.OperationObject = { summary: route.options.summary ?? '', - description: route.options.description, tags: route.options.options?.tags ? extractTags(route.options.options.tags) : [], + ...(route.options.description ? { description: route.options.description } : {}), + ...(route.options.deprecated ? { deprecated: route.options.deprecated } : {}), requestBody: hasBody ? { content: hasVersionFilter From 8641aeea2d3b5c53686a99c2f79fc85ea7676a64 Mon Sep 17 00:00:00 2001 From: Joe McElroy Date: Tue, 18 Jun 2024 16:44:00 +0100 Subject: [PATCH 059/127] [Search] [Playground] Semantic text support (#186268) ## Summary This adds semantic_text support to Chat playground. - We detect the presence of semantic_text and favour these fields over any other ones. - We do a nested query if the field is a semantic_text type, and use the inner_hits to populate the context - This was manually tested through the QA scenarios list and I added a couple more scenarios for semantic_text. - Added to telemetry key with `_SEMANTIC` entry Coverage is still units but this change is pretty well covered. FTRs will follow once we have basic "full chat" flow. ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fetch_query_source_fields.mock.ts | 172 +++++- .../plugins/search_playground/common/types.ts | 15 +- .../edit_context/edit_context_flyout.test.tsx | 2 + .../view_query/view_query_flyout.test.tsx | 9 +- .../view_query/view_query_flyout.tsx | 12 +- .../public/hooks/use_source_indices_field.ts | 2 +- .../hooks/use_source_indices_fields.test.tsx | 23 +- .../public/utils/create_query.test.ts | 502 ++++++++++++------ .../public/utils/create_query.ts | 101 +++- .../server/lib/conversational_chain.test.ts | 51 ++ .../server/lib/elasticsearch_retriever.ts | 2 +- .../lib/fetch_query_source_fields.test.ts | 163 +++++- .../server/lib/fetch_query_source_fields.ts | 101 +++- .../get_value_for_selected_field.test.ts | 54 +- .../utils/get_value_for_selected_field.ts | 16 +- 15 files changed, 993 insertions(+), 232 deletions(-) diff --git a/x-pack/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts b/x-pack/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts index b25ca903c7a4b..d421ad6c8c9b7 100644 --- a/x-pack/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts +++ b/x-pack/plugins/search_playground/__mocks__/fetch_query_source_fields.mock.ts @@ -5,7 +5,177 @@ * 2.0. */ -import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { IndicesGetMappingResponse, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; + +export const SPARSE_SEMANTIC_FIELD_FIELD_CAPS = { + indices: ['test-index2'], + fields: { + infer_field: { + semantic_text: { + type: 'semantic_text', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + 'infer_field.inference.chunks.embeddings': { + sparse_vector: { + type: 'sparse_vector', + metadata_field: false, + searchable: true, + aggregatable: false, + }, + }, + non_infer_field: { + text: { + type: 'text', + metadata_field: false, + searchable: true, + aggregatable: false, + }, + }, + 'infer_field.inference.chunks.text': { + keyword: { + type: 'keyword', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + 'infer_field.inference': { + object: { + type: 'object', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + 'infer_field.inference.chunks': { + nested: { + type: 'nested', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + }, +}; + +export const SPARSE_SEMANTIC_FIELD_MAPPINGS = { + 'test-index2': { + mappings: { + properties: { + infer_field: { + type: 'semantic_text', + inference_id: 'elser-endpoint', + model_settings: { + task_type: 'sparse_embedding', + }, + }, + non_infer_field: { + type: 'text', + }, + }, + }, + }, +} as any as IndicesGetMappingResponse; + +export const DENSE_SEMANTIC_FIELD_MAPPINGS = { + 'test-index2': { + mappings: { + properties: { + infer_field: { + type: 'semantic_text', + inference_id: 'cohere', + model_settings: { + task_type: 'text_embedding', + dimensions: 1536, + similarity: 'dot_product', + }, + }, + non_infer_field: { + type: 'text', + }, + }, + }, + }, +} as any as IndicesGetMappingResponse; + +// for when semantic_text field hasn't been mapped with task_type +// when theres no data / no inference has been performed in the field +export const DENSE_SEMANTIC_FIELD_MAPPINGS_MISSING_TASK_TYPE = { + 'test-index2': { + mappings: { + properties: { + infer_field: { + type: 'semantic_text', + inference_id: 'cohere', + model_settings: { + dimensions: 1536, + similarity: 'dot_product', + }, + }, + non_infer_field: { + type: 'text', + }, + }, + }, + }, +} as any as IndicesGetMappingResponse; + +export const DENSE_SEMANTIC_FIELD_FIELD_CAPS = { + indices: ['test-index2'], + fields: { + infer_field: { + semantic_text: { + type: 'semantic_text', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + 'infer_field.inference.chunks.embeddings': { + sparse_vector: { + type: 'dense_vector', + metadata_field: false, + searchable: true, + aggregatable: false, + }, + }, + non_infer_field: { + text: { + type: 'text', + metadata_field: false, + searchable: true, + aggregatable: false, + }, + }, + 'infer_field.inference.chunks.text': { + keyword: { + type: 'keyword', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + 'infer_field.inference': { + object: { + type: 'object', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + 'infer_field.inference.chunks': { + nested: { + type: 'nested', + metadata_field: false, + searchable: false, + aggregatable: false, + }, + }, + }, +}; export const DENSE_SPARSE_SAME_FIELD_NAME_CAPS = { indices: ['cohere-embeddings', 'elser_index'], diff --git a/x-pack/plugins/search_playground/common/types.ts b/x-pack/plugins/search_playground/common/types.ts index c788b2df1896f..00bfde68ec2ea 100644 --- a/x-pack/plugins/search_playground/common/types.ts +++ b/x-pack/plugins/search_playground/common/types.ts @@ -7,18 +7,25 @@ export type IndicesQuerySourceFields = Record; -interface ModelFields { +interface ModelField { field: string; model_id: string; - nested: boolean; + indices: string[]; +} + +interface SemanticField { + field: string; + inferenceId: string; + embeddingType: 'sparse_vector' | 'dense_vector'; indices: string[]; } export interface QuerySourceFields { - elser_query_fields: ModelFields[]; - dense_vector_query_fields: ModelFields[]; + elser_query_fields: ModelField[]; + dense_vector_query_fields: ModelField[]; bm25_query_fields: string[]; source_fields: string[]; + semantic_fields: SemanticField[]; skipped_fields: number; } diff --git a/x-pack/plugins/search_playground/public/components/edit_context/edit_context_flyout.test.tsx b/x-pack/plugins/search_playground/public/components/edit_context/edit_context_flyout.test.tsx index 4e5bb7f807900..de82892b167be 100644 --- a/x-pack/plugins/search_playground/public/components/edit_context/edit_context_flyout.test.tsx +++ b/x-pack/plugins/search_playground/public/components/edit_context/edit_context_flyout.test.tsx @@ -19,12 +19,14 @@ jest.mock('../../hooks/use_indices_fields', () => ({ dense_vector_query_fields: [], bm25_query_fields: ['field1', 'field2'], source_fields: ['context_field1', 'context_field2'], + semantic_fields: [], }, index2: { elser_query_fields: [], dense_vector_query_fields: [], bm25_query_fields: ['field1', 'field2'], source_fields: ['context_field1', 'context_field2'], + semantic_fields: [], }, }, }), diff --git a/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.test.tsx b/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.test.tsx index 410989eaf52ad..39136e2557296 100644 --- a/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.test.tsx +++ b/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.test.tsx @@ -10,6 +10,7 @@ import { render, fireEvent, screen } from '@testing-library/react'; import { ViewQueryFlyout } from './view_query_flyout'; import { FormProvider, useForm } from 'react-hook-form'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { ChatFormFields } from '../../types'; jest.mock('../../hooks/use_indices_fields', () => ({ useIndicesFields: () => ({ @@ -19,12 +20,14 @@ jest.mock('../../hooks/use_indices_fields', () => ({ dense_vector_query_fields: [], bm25_query_fields: ['field1', 'field2'], skipped_fields: 1, + semantic_fields: [], }, index2: { elser_query_fields: [], dense_vector_query_fields: [], bm25_query_fields: ['field1', 'field2'], skipped_fields: 0, + semantic_fields: [], }, }, }), @@ -41,7 +44,11 @@ jest.mock('../../hooks/use_usage_tracker', () => ({ const MockFormProvider = ({ children }: { children: React.ReactElement }) => { const methods = useForm({ values: { - indices: ['index1', 'index2'], + [ChatFormFields.indices]: ['index1', 'index2'], + [ChatFormFields.sourceFields]: { + index1: ['field1'], + index2: ['field1'], + }, }, }); return {children}; diff --git a/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.tsx b/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.tsx index 64139307de4ba..2fd64f073eac7 100644 --- a/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.tsx +++ b/x-pack/plugins/search_playground/public/components/view_query/view_query_flyout.tsx @@ -65,6 +65,12 @@ const groupTypeQueryFields = ( typeQueryFields += (typeQueryFields ? '_' : '') + 'SPARSE'; } + if ( + selectedFields.some((field) => indexFields.semantic_fields.find((f) => f.field === field)) + ) { + typeQueryFields += (typeQueryFields ? '_' : '') + 'SEMANTIC'; + } + return typeQueryFields; }); @@ -76,6 +82,7 @@ export const ViewQueryFlyout: React.FC = ({ onClose }) => const usageTracker = useUsageTracker(); const { getValues } = useFormContext(); const selectedIndices: string[] = getValues(ChatFormFields.indices); + const sourceFields = getValues(ChatFormFields.sourceFields); const { fields } = useIndicesFields(selectedIndices); const defaultFields = getDefaultQueryFields(fields); @@ -111,7 +118,7 @@ export const ViewQueryFlyout: React.FC = ({ onClose }) => const saveQuery = () => { queryFieldsOnChange(tempQueryFields); - elasticsearchQueryChange(createQuery(tempQueryFields, fields)); + elasticsearchQueryChange(createQuery(tempQueryFields, sourceFields, fields)); onClose(); const groupedQueryFields = groupTypeQueryFields(fields, tempQueryFields); @@ -168,7 +175,7 @@ export const ViewQueryFlyout: React.FC = ({ onClose }) => lineNumbers data-test-subj="ViewElasticsearchQueryResult" > - {JSON.stringify(createQuery(tempQueryFields, fields), null, 2)} + {JSON.stringify(createQuery(tempQueryFields, sourceFields, fields), null, 2)} @@ -198,6 +205,7 @@ export const ViewQueryFlyout: React.FC = ({ onClose }) => aria-label="Select query fields" data-test-subj={`queryFieldsSelectable_${index}`} options={[ + ...group.semantic_fields, ...group.elser_query_fields, ...group.dense_vector_query_fields, ...group.bm25_query_fields, diff --git a/x-pack/plugins/search_playground/public/hooks/use_source_indices_field.ts b/x-pack/plugins/search_playground/public/hooks/use_source_indices_field.ts index 342be7c191778..bc9a37060fb6f 100644 --- a/x-pack/plugins/search_playground/public/hooks/use_source_indices_field.ts +++ b/x-pack/plugins/search_playground/public/hooks/use_source_indices_field.ts @@ -89,7 +89,7 @@ export const useSourceIndicesFields = () => { setNoFieldsIndicesWarning(null); } - onElasticsearchQueryChange(createQuery(defaultFields, fields)); + onElasticsearchQueryChange(createQuery(defaultFields, defaultSourceFields, fields)); onSourceFieldsChange(defaultSourceFields); usageTracker?.count( AnalyticsEvents.sourceFieldsLoaded, diff --git a/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx b/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx index f3b19e8d4360e..7dd1a43d6fc01 100644 --- a/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx +++ b/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx @@ -36,7 +36,6 @@ describe.skip('useSourceIndicesFields Hook', () => { { field: 'field1', model_id: 'model1', - nested: false, indices: ['newIndex'], }, ], @@ -44,6 +43,7 @@ describe.skip('useSourceIndicesFields Hook', () => { bm25_query_fields: [], source_fields: ['field1'], skipped_fields: 0, + semantic_fields: [], }, }; @@ -87,11 +87,11 @@ describe.skip('useSourceIndicesFields Hook', () => { expect(result.current.indices).toEqual([]); expect(getValues()).toMatchInlineSnapshot(` Object { - "doc_size": 5, + "doc_size": 3, "elasticsearch_query": Object {}, "indices": Array [], "prompt": "You are an assistant for question-answering tasks.", - "source_fields": Array [], + "source_fields": Object {}, } `); result.current.addIndex('newIndex'); @@ -109,16 +109,15 @@ describe.skip('useSourceIndicesFields Hook', () => { expect(result.current.loading).toBe(false); expect(getValues()).toMatchInlineSnapshot(` Object { - "doc_size": 5, + "doc_size": 3, "elasticsearch_query": Object { "retriever": Object { "standard": Object { "query": Object { - "text_expansion": Object { - "field1": Object { - "model_id": "model1", - "model_text": "{query}", - }, + "sparse_vector": Object { + "field": "field1", + "inference_id": "model1", + "query": "{query}", }, }, }, @@ -146,6 +145,7 @@ describe.skip('useSourceIndicesFields Hook', () => { bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -169,7 +169,7 @@ describe.skip('useSourceIndicesFields Hook', () => { expect(result.current.loading).toBe(false); expect(getValues()).toMatchInlineSnapshot(` Object { - "doc_size": 5, + "doc_size": 3, "elasticsearch_query": Object { "retriever": Object { "standard": Object { @@ -199,6 +199,7 @@ describe.skip('useSourceIndicesFields Hook', () => { bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -222,7 +223,7 @@ describe.skip('useSourceIndicesFields Hook', () => { expect(result.current.loading).toBe(false); expect(getValues()).toMatchInlineSnapshot(` Object { - "doc_size": 5, + "doc_size": 3, "elasticsearch_query": Object { "retriever": Object { "standard": Object { diff --git a/x-pack/plugins/search_playground/public/utils/create_query.test.ts b/x-pack/plugins/search_playground/public/utils/create_query.test.ts index 282326f0991d2..164f79618d74c 100644 --- a/x-pack/plugins/search_playground/public/utils/create_query.test.ts +++ b/x-pack/plugins/search_playground/public/utils/create_query.test.ts @@ -9,6 +9,8 @@ import { IndicesQuerySourceFields } from '../types'; import { createQuery, getDefaultQueryFields, getDefaultSourceFields } from './create_query'; describe('create_query', () => { + const sourceFields = { index1: [], index2: [] }; + describe('createQuery', () => { it('should return a sparse single query', () => { const fields = { @@ -17,25 +19,23 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { standard: { query: { - text_expansion: { - field1: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field1', + inference_id: 'model1', + query: '{query}', }, }, }, @@ -51,16 +51,15 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { elser_query_fields: [], - dense_vector_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + dense_vector_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { standard: { query: { @@ -89,33 +88,34 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1', 'index2'] }, + { field: 'field1', model_id: 'model1', indices: ['index1', 'index2'] }, ], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1', 'index2'] }, + { field: 'field1', model_id: 'model1', indices: ['index1', 'index2'] }, ], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { standard: { query: { - text_expansion: { - field1: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field1', + inference_id: 'model1', + query: '{query}', }, }, }, @@ -131,37 +131,34 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { - elser_query_fields: [ - { field: 'field2', model_id: 'model1', nested: false, indices: ['index2'] }, - ], + elser_query_fields: [{ field: 'field2', model_id: 'model1', indices: ['index2'] }], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { rrf: { retrievers: [ { standard: { query: { - text_expansion: { - field1: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field1', + inference_id: 'model1', + query: '{query}', }, }, }, @@ -169,11 +166,10 @@ describe('create_query', () => { { standard: { query: { - text_expansion: { - field2: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field2', + inference_id: 'model1', + query: '{query}', }, }, }, @@ -184,72 +180,6 @@ describe('create_query', () => { }); }); - it('should return empty for nested dense query', () => { - const fields = { - index1: ['passages.field1.predicted_value'], - }; - - const fieldDescriptors: IndicesQuerySourceFields = { - index1: { - elser_query_fields: [], - dense_vector_query_fields: [ - { - field: 'passages.field1.predicted_value', - model_id: 'model1', - nested: true, - indices: ['index1'], - }, - ], - bm25_query_fields: [], - source_fields: [], - skipped_fields: 0, - }, - }; - - expect(createQuery(fields, fieldDescriptors)).toEqual({ - retriever: { - standard: { - query: { - match_all: {}, - }, - }, - }, - }); - }); - - it('should return empty for nested sparse query', () => { - const fields = { - index1: ['passages.field1.tokens'], - }; - - const fieldDescriptors: IndicesQuerySourceFields = { - index1: { - elser_query_fields: [ - { - field: 'passages.field1.tokens', - model_id: 'model1', - nested: true, - indices: ['index1'], - }, - ], - dense_vector_query_fields: [], - bm25_query_fields: [], - source_fields: [], - skipped_fields: 0, - }, - }; - - expect(createQuery(fields, fieldDescriptors)).toEqual({ - retriever: { - standard: { - query: { - match_all: {}, - }, - }, - }, - }); - }); - describe('hybrid without RRF', () => { it('should return a hybrid query', () => { const fields = { @@ -259,37 +189,34 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [], bm25_query_fields: ['content', 'title'], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { - elser_query_fields: [ - { field: 'field2', model_id: 'model1', nested: false, indices: ['index2'] }, - ], + elser_query_fields: [{ field: 'field2', model_id: 'model1', indices: ['index2'] }], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors, { rrf: false })).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors, { rrf: false })).toEqual({ retriever: { standard: { query: { bool: { should: [ { - text_expansion: { - field1: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field1', + inference_id: 'model1', + query: '{query}', }, }, { @@ -299,11 +226,10 @@ describe('create_query', () => { }, }, { - text_expansion: { - field2: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field2', + inference_id: 'model1', + query: '{query}', }, }, ], @@ -325,37 +251,34 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [], bm25_query_fields: ['content', 'title'], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { - elser_query_fields: [ - { field: 'field2', model_id: 'model1', nested: false, indices: ['index2'] }, - ], + elser_query_fields: [{ field: 'field2', model_id: 'model1', indices: ['index2'] }], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { rrf: { retrievers: [ { standard: { query: { - text_expansion: { - field1: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field1', + inference_id: 'model1', + query: '{query}', }, }, }, @@ -373,11 +296,10 @@ describe('create_query', () => { { standard: { query: { - text_expansion: { - field2: { - model_id: 'model1', - model_text: '{query}', - }, + sparse_vector: { + field: 'field2', + inference_id: 'model1', + query: '{query}', }, }, }, @@ -397,25 +319,23 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { elser_query_fields: [], - dense_vector_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + dense_vector_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], bm25_query_fields: ['content', 'title'], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { - elser_query_fields: [ - { field: 'field2', model_id: 'model1', nested: false, indices: ['index2'] }, - ], + elser_query_fields: [{ field: 'field2', model_id: 'model1', indices: ['index2'] }], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { standard: { query: { @@ -444,16 +364,15 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { elser_query_fields: [], - dense_vector_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + dense_vector_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], bm25_query_fields: ['content', 'title'], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; - expect(createQuery(fields, fieldDescriptors)).toEqual({ + expect(createQuery(fields, sourceFields, fieldDescriptors)).toEqual({ retriever: { rrf: { retrievers: [ @@ -488,21 +407,262 @@ describe('create_query', () => { }, }); }); + + describe('semantic fields', () => { + describe('sparse_vector embedding', () => { + it('should return a query with semantic field, specified as a source field', () => { + // as the field is specified as a source field, it should use the nested query and manually calling the sparse_vector query + const fields = { + index1: ['field2', 'title', 'content'], + }; + + const fieldDescriptors: IndicesQuerySourceFields = { + index1: { + elser_query_fields: [], + dense_vector_query_fields: [ + { field: 'field1', model_id: 'model1', indices: ['index1'] }, + ], + bm25_query_fields: ['content', 'title'], + source_fields: [], + skipped_fields: 0, + semantic_fields: [ + { + field: 'field2', + inferenceId: 'model2', + indices: ['index1'], + embeddingType: 'sparse_vector', + }, + ], + }, + }; + + expect( + createQuery( + fields, + { + index1: ['field2'], + }, + fieldDescriptors + ) + ).toEqual({ + retriever: { + rrf: { + retrievers: [ + { + standard: { + query: { + nested: { + inner_hits: { _source: ['field2.inference.chunks.text'], size: 2 }, + path: 'field2.inference.chunks', + query: { + sparse_vector: { + field: 'field2.inference.chunks.embeddings', + inference_id: 'model2', + query: '{query}', + }, + }, + }, + }, + }, + }, + { + standard: { + query: { multi_match: { fields: ['title', 'content'], query: '{query}' } }, + }, + }, + ], + }, + }, + }); + }); + + it('should return a query with semantic field, specified not as a source field', () => { + // this should fallback to using the semantic field for querying + const fields = { + index1: ['field2', 'title', 'content'], + }; + + const fieldDescriptors: IndicesQuerySourceFields = { + index1: { + elser_query_fields: [], + dense_vector_query_fields: [ + { field: 'field1', model_id: 'model1', indices: ['index1'] }, + ], + bm25_query_fields: ['content', 'title'], + source_fields: [], + skipped_fields: 0, + semantic_fields: [ + { + field: 'field2', + inferenceId: 'model2', + indices: ['index1'], + embeddingType: 'sparse_vector', + }, + ], + }, + }; + + expect( + createQuery( + fields, + { + index1: ['content'], + }, + fieldDescriptors + ) + ).toEqual({ + retriever: { + rrf: { + retrievers: [ + { standard: { query: { semantic: { field: 'field2', query: '{query}' } } } }, + { + standard: { + query: { multi_match: { fields: ['title', 'content'], query: '{query}' } }, + }, + }, + ], + }, + }, + }); + }); + }); + + describe('dense embedding', () => { + it('should return a query with semantic field, specified as a source field', () => { + // as the field is specified as a source field, it should use the nested query and manually calling the knn query + const fields = { + index1: ['field2', 'title', 'content'], + }; + + const fieldDescriptors: IndicesQuerySourceFields = { + index1: { + elser_query_fields: [], + dense_vector_query_fields: [ + { field: 'field1', model_id: 'model1', indices: ['index1'] }, + ], + bm25_query_fields: ['content', 'title'], + source_fields: [], + skipped_fields: 0, + semantic_fields: [ + { + field: 'field2', + inferenceId: 'model2', + indices: ['index1'], + embeddingType: 'dense_vector', + }, + ], + }, + }; + + expect( + createQuery( + fields, + { + index1: ['field2'], + }, + fieldDescriptors + ) + ).toEqual({ + retriever: { + rrf: { + retrievers: [ + { + standard: { + query: { + nested: { + inner_hits: { _source: ['field2.inference.chunks.text'], size: 2 }, + path: 'field2.inference.chunks', + query: { + knn: { + field: 'field2.inference.chunks.embeddings', + query_vector_builder: { + text_embedding: { + model_id: 'model2', + model_text: '{query}', + }, + }, + }, + }, + }, + }, + }, + }, + { + standard: { + query: { multi_match: { fields: ['title', 'content'], query: '{query}' } }, + }, + }, + ], + }, + }, + }); + }); + + it('should return a query with semantic field, specified not as a source field', () => { + // this should fallback to using the semantic field for querying + const fields = { + index1: ['field2', 'title', 'content'], + }; + + const fieldDescriptors: IndicesQuerySourceFields = { + index1: { + elser_query_fields: [], + dense_vector_query_fields: [ + { field: 'field1', model_id: 'model1', indices: ['index1'] }, + ], + bm25_query_fields: ['content', 'title'], + source_fields: [], + skipped_fields: 0, + semantic_fields: [ + { + field: 'field2', + inferenceId: 'model2', + indices: ['index1'], + embeddingType: 'dense_vector', + }, + ], + }, + }; + + expect( + createQuery( + fields, + { + index1: ['content'], + }, + fieldDescriptors + ) + ).toEqual({ + retriever: { + rrf: { + retrievers: [ + { standard: { query: { semantic: { field: 'field2', query: '{query}' } } } }, + { + standard: { + query: { multi_match: { fields: ['title', 'content'], query: '{query}' } }, + }, + }, + ], + }, + }, + }); + }); + }); + }); }); describe('getDefaultQueryFields', () => { it('should return default ELSER query fields', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [ - { field: 'field1', model_id: 'dense_model', nested: false, indices: ['index1'] }, + { field: 'field1', model_id: 'dense_model', indices: ['index1'] }, ], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -512,36 +672,34 @@ describe('create_query', () => { it('should return default elser query fields for multiple indices', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [ { field: 'dv_field1', model_id: 'dense_model', - nested: false, + indices: ['index1', 'index2'], }, ], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { - elser_query_fields: [ - { field: 'vector', model_id: 'model1', nested: false, indices: ['index2'] }, - ], + elser_query_fields: [{ field: 'vector', model_id: 'model1', indices: ['index2'] }], dense_vector_query_fields: [ { field: 'dv_field1', model_id: 'dense_model', - nested: false, + indices: ['index1', 'index2'], }, ], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -554,36 +712,34 @@ describe('create_query', () => { it('should return elser query fields for default fields', () => { const fieldDescriptors: IndicesQuerySourceFields = { index1: { - elser_query_fields: [ - { field: 'field1', model_id: 'model1', nested: false, indices: ['index1'] }, - ], + elser_query_fields: [{ field: 'field1', model_id: 'model1', indices: ['index1'] }], dense_vector_query_fields: [ { field: 'dv_field1', model_id: 'dense_model', - nested: false, + indices: ['index1', 'index2'], }, ], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, index2: { - elser_query_fields: [ - { field: 'vector', model_id: 'model1', nested: false, indices: ['index2'] }, - ], + elser_query_fields: [{ field: 'vector', model_id: 'model1', indices: ['index2'] }], dense_vector_query_fields: [ { field: 'dv_field1', model_id: 'dense_model', - nested: false, + indices: ['index1', 'index2'], }, ], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -598,11 +754,12 @@ describe('create_query', () => { index1: { elser_query_fields: [], dense_vector_query_fields: [ - { field: 'dv_field1', model_id: 'dense_model', nested: false, indices: ['index1'] }, + { field: 'dv_field1', model_id: 'dense_model', indices: ['index1'] }, ], bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -617,6 +774,7 @@ describe('create_query', () => { bm25_query_fields: ['title', 'text', 'content'], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -633,6 +791,7 @@ describe('create_query', () => { bm25_query_fields: ['unknown1', 'unknown2'], source_fields: [], skipped_fields: 0, + semantic_fields: [], }, }; @@ -648,6 +807,7 @@ describe('create_query', () => { 'search-search-labs': { elser_query_fields: [], dense_vector_query_fields: [], + semantic_fields: [], bm25_query_fields: [ 'additional_urls', 'title', @@ -695,6 +855,7 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { 'search-search-labs': { elser_query_fields: [], + semantic_fields: [], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: [], @@ -713,6 +874,7 @@ describe('create_query', () => { const fieldDescriptors: IndicesQuerySourceFields = { 'search-search-labs': { elser_query_fields: [], + semantic_fields: [], dense_vector_query_fields: [], bm25_query_fields: [], source_fields: ['non_suggested_field'], diff --git a/x-pack/plugins/search_playground/public/utils/create_query.ts b/x-pack/plugins/search_playground/public/utils/create_query.ts index b2602a45707a8..0f65bea734d5c 100644 --- a/x-pack/plugins/search_playground/public/utils/create_query.ts +++ b/x-pack/plugins/search_playground/public/utils/create_query.ts @@ -46,6 +46,7 @@ interface ReRankOptions { export function createQuery( fields: IndexFields, + sourceFields: IndexFields, fieldDescriptors: IndicesQuerySourceFields, rerankOptions: ReRankOptions = { rrf: true, @@ -57,19 +58,83 @@ export function createQuery( const indexFields: string[] = fields[index]; const indexFieldDescriptors: QuerySourceFields = fieldDescriptors[index]; + const semanticMatches = indexFields.map((field) => { + const semanticField = indexFieldDescriptors.semantic_fields.find((x) => x.field === field); + const isSourceField = sourceFields[index].includes(field); + + // this is needed to get the inner_hits for the source field + // we cant rely on only the semantic field + // in future inner_hits option will be added to semantic + if (semanticField && isSourceField) { + if (semanticField.embeddingType === 'dense_vector') { + const filter = + semanticField.indices.length < indices.length + ? { filter: { terms: { _index: semanticField.indices } } } + : {}; + + return { + nested: { + path: `${semanticField.field}.inference.chunks`, + query: { + knn: { + field: `${semanticField.field}.inference.chunks.embeddings`, + ...filter, + query_vector_builder: { + text_embedding: { + model_id: semanticField.inferenceId, + model_text: '{query}', + }, + }, + }, + }, + inner_hits: { + size: 2, + _source: [`${semanticField.field}.inference.chunks.text`], + }, + }, + }; + } else if (semanticField.embeddingType === 'sparse_vector') { + return { + nested: { + path: `${semanticField.field}.inference.chunks`, + query: { + sparse_vector: { + inference_id: semanticField.inferenceId, + field: `${semanticField.field}.inference.chunks.embeddings`, + query: '{query}', + }, + }, + inner_hits: { + size: 2, + _source: [`${semanticField.field}.inference.chunks.text`], + }, + }, + }; + } + } else if (semanticField) { + return { + semantic: { + field: semanticField.field, + query: '{query}', + }, + }; + } else { + return null; + } + }); + const sparseMatches = indexFields.map((field) => { const elserField = indexFieldDescriptors.elser_query_fields.find( (x) => x.field === field ); - // not supporting nested fields for now - if (elserField && !elserField.nested) { + if (elserField) { // when another index has the same field, we don't want to duplicate the match rule const hasExistingSparseMatch = acc.queryMatches.find( - (x: any) => - x?.text_expansion?.[field] && - x?.text_expansion?.[field].model_id === elserField?.model_id + (x) => + x?.sparse_vector?.field === field && + x?.sparse_vector?.inference_id === elserField?.model_id ); if (hasExistingSparseMatch) { @@ -77,11 +142,10 @@ export function createQuery( } return { - text_expansion: { - [elserField.field]: { - model_id: elserField.model_id, - model_text: '{query}', - }, + sparse_vector: { + field: elserField.field, + inference_id: elserField.model_id, + query: '{query}', }, }; } @@ -108,8 +172,7 @@ export function createQuery( (x) => x.field === field ); - // not supporting nested fields for now - if (denseVectorField && !denseVectorField.nested) { + if (denseVectorField) { // when the knn field isn't found in all indices, we need a filter to ensure we only use the field from the correct index const filter = denseVectorField.indices.length < indices.length @@ -134,7 +197,7 @@ export function createQuery( }) .filter((x) => !!x); - const matches = [...sparseMatches, bm25Match].filter((x) => !!x); + const matches = [...sparseMatches, ...semanticMatches, bm25Match].filter((x) => !!x); return { queryMatches: [...acc.queryMatches, ...matches], @@ -222,6 +285,14 @@ export function getDefaultSourceFields(fieldDescriptors: IndicesQuerySourceField (acc: IndexFields, index: string) => { const indexFieldDescriptors = fieldDescriptors[index]; + // semantic_text fields are prioritized + if (indexFieldDescriptors.semantic_fields.length > 0) { + return { + ...acc, + [index]: indexFieldDescriptors.semantic_fields.map((x) => x.field), + }; + } + // if there are no source fields, we don't need to suggest anything if (indexFieldDescriptors.source_fields.length === 0) { return { @@ -253,7 +324,9 @@ export function getDefaultQueryFields(fieldDescriptors: IndicesQuerySourceFields const indexFieldDescriptors = fieldDescriptors[index]; const fields: string[] = []; - if (indexFieldDescriptors.elser_query_fields.length > 0) { + if (indexFieldDescriptors.semantic_fields.length > 0) { + fields.push(...indexFieldDescriptors.semantic_fields.map((x) => x.field)); + } else if (indexFieldDescriptors.elser_query_fields.length > 0) { const suggested = indexFieldDescriptors.elser_query_fields.filter((x) => SUGGESTED_SPARSE_FIELDS.includes(x.field) ); diff --git a/x-pack/plugins/search_playground/server/lib/conversational_chain.test.ts b/x-pack/plugins/search_playground/server/lib/conversational_chain.test.ts index ddc95d9dd4346..f7ad46d3fdfda 100644 --- a/x-pack/plugins/search_playground/server/lib/conversational_chain.test.ts +++ b/x-pack/plugins/search_playground/server/lib/conversational_chain.test.ts @@ -208,6 +208,57 @@ describe('conversational chain', () => { }); }, 10000); + it('should be able to create a conversational chain with inner hit field', async () => { + await createTestChain({ + responses: ['the final answer'], + chat: [ + { + id: '1', + role: 'user', + content: 'what is the work from home policy?', + }, + ], + expectedFinalAnswer: 'the final answer', + docs: [ + { + _index: 'index', + _id: '1', + inner_hits: { + 'field.inference.chunks': { + hits: { + hits: [ + { + _source: { + text: 'value', + }, + }, + ], + }, + }, + }, + }, + ], + expectedDocs: [ + { + documents: [{ metadata: { _id: '1', _index: 'index' }, pageContent: 'value' }], + type: 'retrieved_docs', + }, + ], + expectedTokens: [ + { type: 'context_token_count', count: 7 }, + { type: 'prompt_token_count', count: 20 }, + ], + expectedSearchRequest: [ + { + method: 'POST', + path: '/index,website/_search', + body: { query: { match: { field: 'what is the work from home policy?' } }, size: 3 }, + }, + ], + contentField: { index: 'field' }, + }); + }, 10000); + it('asking with chat history should re-write the question', async () => { await createTestChain({ responses: ['rewrite the question', 'the final answer'], diff --git a/x-pack/plugins/search_playground/server/lib/elasticsearch_retriever.ts b/x-pack/plugins/search_playground/server/lib/elasticsearch_retriever.ts index 4a2c3344b2934..8504651bb6398 100644 --- a/x-pack/plugins/search_playground/server/lib/elasticsearch_retriever.ts +++ b/x-pack/plugins/search_playground/server/lib/elasticsearch_retriever.ts @@ -89,7 +89,7 @@ export class ElasticsearchRetriever extends BaseRetriever { : this.content_field[hit._index as string]; // we need to iterate over the _source object to get the value of complex key definition such as metadata.source - const valueForSelectedField = getValueForSelectedField(hit._source, pageContentFieldKey); + const valueForSelectedField = getValueForSelectedField(hit, pageContentFieldKey); return new Document({ pageContent: valueForSelectedField, diff --git a/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.test.ts b/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.test.ts index 539a3deaa7c03..8991cb9924480 100644 --- a/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.test.ts +++ b/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.test.ts @@ -19,8 +19,13 @@ import { SPARSE_INPUT_OUTPUT_ONE_INDEX, SPARSE_INPUT_OUTPUT_ONE_INDEX_FIELD_CAPS, SPARSE_INPUT_OUTPUT_ONE_INDEX_FIELD_CAPS_MODEL_ID_KEYWORD, + SPARSE_SEMANTIC_FIELD_FIELD_CAPS, + SPARSE_SEMANTIC_FIELD_MAPPINGS, DENSE_SPARSE_SAME_FIELD_NAME_CAPS, DENSE_SPARSE_SAME_FIELD_NAME_DOCS, + DENSE_SEMANTIC_FIELD_MAPPINGS, + DENSE_SEMANTIC_FIELD_FIELD_CAPS, + DENSE_SEMANTIC_FIELD_MAPPINGS_MISSING_TASK_TYPE, } from '../../__mocks__/fetch_query_source_fields.mock'; import { fetchFields, @@ -36,10 +41,20 @@ describe('fetch_query_source_fields', () => { { index: 'workplace_index', doc: ELSER_PASSAGE_CHUNKED_TWO_INDICES_DOCS[0], + mapping: { + workplace_index: { + mappings: {}, + }, + }, }, { index: 'workplace_index2', doc: ELSER_PASSAGE_CHUNKED_TWO_INDICES_DOCS[1], + mapping: { + workplace_index2: { + mappings: {}, + }, + }, }, ]) ).toEqual({ @@ -55,14 +70,15 @@ describe('fetch_query_source_fields', () => { { field: 'vector.tokens', model_id: '.elser_model_2', - nested: false, indices: ['workplace_index'], }, ], skipped_fields: 8, source_fields: ['metadata.summary', 'metadata.rolePermissions', 'text', 'metadata.name'], + semantic_fields: [], }, workplace_index2: { + semantic_fields: [], bm25_query_fields: [ 'metadata.summary', 'content', @@ -75,7 +91,6 @@ describe('fetch_query_source_fields', () => { { field: 'content_vector.tokens', model_id: '.elser_model_2', - nested: false, indices: ['workplace_index2'], }, ], @@ -95,10 +110,16 @@ describe('fetch_query_source_fields', () => { { index: 'search-example-main', doc: DENSE_PASSAGE_FIRST_SINGLE_INDEX_DOC, + mapping: { + 'search-example-main': { + mappings: {}, + }, + }, }, ]) ).toEqual({ 'search-example-main': { + semantic_fields: [], bm25_query_fields: [ 'page_content_key', 'title', @@ -118,7 +139,6 @@ describe('fetch_query_source_fields', () => { { field: 'page_content_e5_embbeding.predicted_value', model_id: '.multilingual-e5-small_linux-x86_64', - nested: false, indices: ['search-example-main'], }, ], @@ -149,18 +169,23 @@ describe('fetch_query_source_fields', () => { { index: 'search-nethys', doc: SPARSE_DOC_SINGLE_INDEX, + mapping: { + 'search-nethys': { + mappings: {}, + }, + }, }, ]) ).toEqual({ 'search-nethys': { bm25_query_fields: ['body_content', 'headings', 'title'], dense_vector_query_fields: [], + semantic_fields: [], elser_query_fields: [ { field: 'ml.inference.body_content_expanded.predicted_value', indices: ['search-nethys'], model_id: '.elser_model_2_linux-x86_64', - nested: false, }, ], source_fields: ['body_content', 'headings', 'title'], @@ -176,6 +201,11 @@ describe('fetch_query_source_fields', () => { { index: 'workplace_index_nested', doc: DENSE_VECTOR_DOCUMENT_FIRST[0], + mapping: { + workplace_index_nested: { + mappings: {}, + }, + }, }, ]) ).toEqual({ @@ -192,6 +222,7 @@ describe('fetch_query_source_fields', () => { ], dense_vector_query_fields: [], elser_query_fields: [], + semantic_fields: [], source_fields: [ 'metadata.category', 'content', @@ -213,6 +244,11 @@ describe('fetch_query_source_fields', () => { { index: 'index2', doc: DENSE_INPUT_OUTPUT_ONE_INDEX[0], + mapping: { + index2: { + mappings: {}, + }, + }, }, ]) ).toEqual({ @@ -223,10 +259,10 @@ describe('fetch_query_source_fields', () => { field: 'text_embedding', indices: ['index2'], model_id: '.multilingual-e5-small', - nested: false, }, ], elser_query_fields: [], + semantic_fields: [], source_fields: ['text'], skipped_fields: 2, }, @@ -239,6 +275,11 @@ describe('fetch_query_source_fields', () => { { index: 'index', doc: SPARSE_INPUT_OUTPUT_ONE_INDEX[0], + mapping: { + index: { + mappings: {}, + }, + }, }, ]) ).toEqual({ @@ -249,10 +290,10 @@ describe('fetch_query_source_fields', () => { field: 'text_embedding', indices: ['index'], model_id: '.elser_model_2', - nested: false, }, ], dense_vector_query_fields: [], + semantic_fields: [], source_fields: ['text'], skipped_fields: 2, }, @@ -265,10 +306,20 @@ describe('fetch_query_source_fields', () => { { index: 'cohere-embeddings', doc: DENSE_SPARSE_SAME_FIELD_NAME_DOCS[0], + mapping: { + 'cohere-embeddings': { + mappings: {}, + }, + }, }, { index: 'elser_index', doc: DENSE_SPARSE_SAME_FIELD_NAME_DOCS[1], + mapping: { + elser_index: { + mappings: {}, + }, + }, }, ]) ).toEqual({ @@ -279,12 +330,12 @@ describe('fetch_query_source_fields', () => { field: 'text_embedding', indices: ['cohere-embeddings'], model_id: 'cohere_embeddings', - nested: false, }, ], elser_query_fields: [], skipped_fields: 2, source_fields: ['text'], + semantic_fields: [], }, elser_index: { bm25_query_fields: ['text'], @@ -294,14 +345,96 @@ describe('fetch_query_source_fields', () => { field: 'text_embedding', indices: ['elser_index'], model_id: 'my-elser-model', - nested: false, }, ], skipped_fields: 2, source_fields: ['text'], + semantic_fields: [], }, }); }); + + describe('semantic text support', () => { + it('should return the correct fields for semantic text - sparse', () => { + expect( + parseFieldsCapabilities(SPARSE_SEMANTIC_FIELD_FIELD_CAPS, [ + { + index: 'test-index2', + // unused + doc: SPARSE_INPUT_OUTPUT_ONE_INDEX[0], + mapping: SPARSE_SEMANTIC_FIELD_MAPPINGS, + }, + ]) + ).toEqual({ + 'test-index2': { + bm25_query_fields: ['non_infer_field'], + dense_vector_query_fields: [], + elser_query_fields: [], + semantic_fields: [ + { + embeddingType: 'sparse_vector', + field: 'infer_field', + inferenceId: 'elser-endpoint', + indices: ['test-index2'], + }, + ], + skipped_fields: 4, + source_fields: ['infer_field', 'non_infer_field'], + }, + }); + }); + + it('should return the correct fields for semantic text - dense', () => { + expect( + parseFieldsCapabilities(DENSE_SEMANTIC_FIELD_FIELD_CAPS, [ + { + index: 'test-index2', + // unused + doc: DENSE_INPUT_OUTPUT_ONE_INDEX[0], + mapping: DENSE_SEMANTIC_FIELD_MAPPINGS, + }, + ]) + ).toEqual({ + 'test-index2': { + bm25_query_fields: ['non_infer_field'], + dense_vector_query_fields: [], + elser_query_fields: [], + semantic_fields: [ + { + embeddingType: 'dense_vector', + field: 'infer_field', + inferenceId: 'cohere', + indices: ['test-index2'], + }, + ], + skipped_fields: 4, + source_fields: ['infer_field', 'non_infer_field'], + }, + }); + }); + + it('skips if the semantic_text field not setup correctly', () => { + expect( + parseFieldsCapabilities(DENSE_SEMANTIC_FIELD_FIELD_CAPS, [ + { + index: 'test-index2', + // unused + doc: DENSE_INPUT_OUTPUT_ONE_INDEX[0], + mapping: DENSE_SEMANTIC_FIELD_MAPPINGS_MISSING_TASK_TYPE, + }, + ]) + ).toEqual({ + 'test-index2': { + bm25_query_fields: ['non_infer_field'], + dense_vector_query_fields: [], + elser_query_fields: [], + semantic_fields: [], + skipped_fields: 5, // increat by 1 for the semantic field + source_fields: ['non_infer_field'], + }, + }); + }); + }); }); describe('getModelIdFields', () => { @@ -340,6 +473,13 @@ describe('fetch_query_source_fields', () => { asCurrentUser: { fieldCaps: jest.fn().mockResolvedValue(DENSE_PASSAGE_FIRST_SINGLE_INDEX_FIELD_CAPS), search: jest.fn().mockResolvedValue(DENSE_PASSAGE_FIRST_SINGLE_INDEX_DOC), + indices: { + getMapping: jest.fn().mockResolvedValue({ + 'search-example-main': { + mappings: {}, + }, + }), + }, }, } as any; const indices = ['search-example-main']; @@ -371,6 +511,13 @@ describe('fetch_query_source_fields', () => { asCurrentUser: { fieldCaps: jest.fn().mockResolvedValue(SPARSE_INPUT_OUTPUT_ONE_INDEX_FIELD_CAPS), search: jest.fn().mockResolvedValue(SPARSE_INPUT_OUTPUT_ONE_INDEX), + indices: { + getMapping: jest.fn().mockResolvedValue({ + index: { + mappings: {}, + }, + }), + }, }, } as any; const indices = ['index']; diff --git a/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.ts b/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.ts index 82db1b8de6df4..15e1ead0bf037 100644 --- a/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.ts +++ b/x-pack/plugins/search_playground/server/lib/fetch_query_source_fields.ts @@ -5,8 +5,14 @@ * 2.0. */ -import { SearchResponse, FieldCapsResponse } from '@elastic/elasticsearch/lib/api/types'; -import { FieldCapsFieldCapability } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { + SearchResponse, + FieldCapsResponse, + IndicesGetMappingResponse, + FieldCapsFieldCapability, + MappingPropertyBase, +} from '@elastic/elasticsearch/lib/api/types'; + import { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; import { IndicesQuerySourceFields } from '../types'; @@ -15,11 +21,35 @@ interface FieldModelId { modelId: string | undefined; } +type SemanticEmbeddingType = 'sparse_vector' | 'dense_vector'; + +interface SemanticField { + field: string; + inferenceId: string; + embeddingType?: SemanticEmbeddingType; +} + interface IndexFieldModel { index: string; fields: FieldModelId[]; + semanticTextFields: SemanticField[]; } +type TaskType = 'sparse_embedding' | 'text_embedding'; + +interface MappingSemanticTextProperty extends MappingPropertyBase { + type: 'semantic_text'; + inference_id: string; + model_settings?: { + task_type: TaskType; + }; +} + +const EMBEDDING_TYPE: Record = { + sparse_embedding: 'sparse_vector', + text_embedding: 'dense_vector', +}; + export const getModelIdFields = (fieldCapsResponse: FieldCapsResponse) => { const { fields } = fieldCapsResponse; return Object.keys(fields).reduce>((acc, fieldKey) => { @@ -64,7 +94,7 @@ export const fetchFields = async ( const modelIdFields = getModelIdFields(fieldCapabilities); - const indicesAggs = await Promise.all( + const indicesAggsMappings = await Promise.all( indices.map(async (index) => ({ index, doc: await client.asCurrentUser.search({ @@ -85,14 +115,19 @@ export const fetchFields = async ( ), }, }), + mapping: await client.asCurrentUser.indices.getMapping({ index }), })) ); - return parseFieldsCapabilities(fieldCapabilities, indicesAggs); + return parseFieldsCapabilities(fieldCapabilities, indicesAggsMappings); }; const INFERENCE_MODEL_FIELD_REGEXP = /\.predicted_value|\.tokens/; +const getSemanticField = (field: string, semanticFields: SemanticField[]) => { + return semanticFields.find((sf) => sf.field === field); +}; + const getModelField = (field: string, modelIdFields: FieldModelId[]) => { // For input_output inferred fields, the model_id is at the top level const topLevelModelField = modelIdFields.find( @@ -141,12 +176,12 @@ const isFieldInIndex = ( export const parseFieldsCapabilities = ( fieldCapsResponse: FieldCapsResponse, - aggDocs: Array<{ index: string; doc: SearchResponse }> + aggMappingDocs: Array<{ index: string; doc: SearchResponse; mapping: IndicesGetMappingResponse }> ): IndicesQuerySourceFields => { const { fields, indices: indexOrIndices } = fieldCapsResponse; const indices = Array.isArray(indexOrIndices) ? indexOrIndices : [indexOrIndices]; - const indexModelIdFields = aggDocs.map((aggDoc) => { + const indexModelIdFields = aggMappingDocs.map((aggDoc) => { const modelIdFields = Object.keys(aggDoc.doc.aggregations || {}).map((field) => { return { field, @@ -154,9 +189,28 @@ export const parseFieldsCapabilities = ( }; }); + const mappingProperties = aggDoc.mapping[aggDoc.index].mappings.properties || {}; + + const semanticTextFields: SemanticField[] = Object.keys(mappingProperties || {}) + .filter( + // @ts-ignore + (field) => mappingProperties[field].type === 'semantic_text' + ) + .map((field) => { + const mapping = mappingProperties[field] as unknown as MappingSemanticTextProperty; + return { + field, + inferenceId: mapping?.inference_id, + embeddingType: mapping?.model_settings?.task_type + ? EMBEDDING_TYPE[mapping.model_settings.task_type] + : undefined, + }; + }); + return { index: aggDoc.index, fields: modelIdFields, + semanticTextFields, }; }); @@ -167,6 +221,7 @@ export const parseFieldsCapabilities = ( bm25_query_fields: [], source_fields: [], skipped_fields: 0, + semantic_fields: [], }; return acc; }, {}); @@ -186,15 +241,38 @@ export const parseFieldsCapabilities = ( : (indices as unknown as string[]); for (const index of indicesPresentIn) { - const modelIdFields = indexModelIdFields.find( + const { fields: modelIdFields, semanticTextFields } = indexModelIdFields.find( (indexModelIdField) => indexModelIdField.index === index - )!.fields; + )!; + const nestedField = isFieldNested(fieldKey, fieldCapsResponse); + + if (isFieldInIndex(field, 'semantic_text', index)) { + const semanticFieldMapping = getSemanticField(fieldKey, semanticTextFields); - if ( + // only use this when embeddingType and inferenceId is defined + // this requires semantic_text field to be set up correctly and ingested + if ( + semanticFieldMapping && + semanticFieldMapping.embeddingType && + semanticFieldMapping.inferenceId && + !nestedField + ) { + const semanticField = { + field: fieldKey, + inferenceId: semanticFieldMapping.inferenceId, + embeddingType: semanticFieldMapping.embeddingType, + indices: (field.semantic_text.indices as string[]) || indicesPresentIn, + }; + + acc[index].semantic_fields.push(semanticField); + acc[index].source_fields.push(fieldKey); + } else { + acc[index].skipped_fields++; + } + } else if ( isFieldInIndex(field, 'rank_features', index) || isFieldInIndex(field, 'sparse_vector', index) ) { - const nestedField = isFieldNested(fieldKey, fieldCapsResponse); const modelId = getModelField(fieldKey, modelIdFields); const fieldCapabilities = field.rank_features || field.sparse_vector; @@ -205,7 +283,6 @@ export const parseFieldsCapabilities = ( const elserModelField = { field: fieldKey, model_id: modelId, - nested: !!isFieldNested(fieldKey, fieldCapsResponse), indices: (fieldCapabilities.indices as string[]) || indicesPresentIn, }; acc[index].elser_query_fields.push(elserModelField); @@ -213,7 +290,6 @@ export const parseFieldsCapabilities = ( acc[index].skipped_fields++; } } else if (isFieldInIndex(field, 'dense_vector', index)) { - const nestedField = isFieldNested(fieldKey, fieldCapsResponse); const modelId = getModelField(fieldKey, modelIdFields); const fieldCapabilities = field.dense_vector; @@ -224,7 +300,6 @@ export const parseFieldsCapabilities = ( const denseVectorField = { field: fieldKey, model_id: modelId, - nested: !!nestedField, indices: (fieldCapabilities.indices as string[]) || indicesPresentIn, }; acc[index].dense_vector_query_fields.push(denseVectorField); diff --git a/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts b/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts index a13e51603cc7b..bf02f6620d38c 100644 --- a/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts +++ b/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.test.ts @@ -22,7 +22,7 @@ describe('getValueForSelectedField', () => { }, }; - expect(getValueForSelectedField(hit._source, 'test')).toEqual('The Shawshank Redemption'); + expect(getValueForSelectedField(hit, 'test')).toEqual('The Shawshank Redemption'); }); test('should return for combined key', () => { @@ -39,7 +39,7 @@ describe('getValueForSelectedField', () => { }, }; - expect(getValueForSelectedField(hit._source, 'metadata.source')).toEqual( + expect(getValueForSelectedField(hit, 'metadata.source')).toEqual( 'Over the course of several years, two convicts form a friendship, seeking consolation and, eventually, redemption through basic compassion' ); }); @@ -58,7 +58,7 @@ describe('getValueForSelectedField', () => { }, }; - expect(getValueForSelectedField(hit._source, 'metadata.sources')).toBe(''); + expect(getValueForSelectedField(hit, 'metadata.sources')).toBe(''); }); test('should return empty string for nested key', () => { @@ -75,6 +75,52 @@ describe('getValueForSelectedField', () => { }, }; - expect(getValueForSelectedField(hit._source, 'bla.sources')).toBe(''); + expect(getValueForSelectedField(hit, 'bla.sources')).toBe(''); + }); + + test('should return when its a chunked passage', () => { + const hit = { + _index: 'sample-index', + _id: '8jSNY48B6iHEi98DL1C-', + _score: 0.7789394, + _source: { + test: 'The Shawshank Redemption', + metadata: { + source: + 'Over the course of several years, two convicts form a friendship, seeking consolation and, eventually, redemption through basic compassion', + }, + }, + inner_hits: { + 'test.inference.chunks': { + hits: { + hits: [ + { + _source: { + text: 'Over the course of several years', + }, + }, + { + _source: { + text: 'two convicts form a friendship', + }, + }, + { + _source: { + text: 'seeking consolation and, eventually, redemption through basic compassion', + }, + }, + ], + }, + }, + }, + }; + + expect(getValueForSelectedField(hit as any, 'test')).toMatchInlineSnapshot(` + "Over the course of several years + --- + two convicts form a friendship + --- + seeking consolation and, eventually, redemption through basic compassion" + `); }); }); diff --git a/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.ts b/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.ts index 6a2044f2943e4..68bd600d62143 100644 --- a/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.ts +++ b/x-pack/plugins/search_playground/server/utils/get_value_for_selected_field.ts @@ -5,8 +5,20 @@ * 2.0. */ +import { SearchHit } from '@elastic/elasticsearch/lib/api/types'; import { get } from 'lodash'; -export const getValueForSelectedField = (source: unknown, path: string): string => { - return get(source, path, ''); +export const getValueForSelectedField = (hit: SearchHit, path: string): string => { + if (!hit) { + return ''; + } + + // for semantic_text matches + if (!!hit.inner_hits?.[`${path}.inference.chunks`]) { + return hit.inner_hits[`${path}.inference.chunks`].hits.hits + .map((innerHit) => innerHit._source.text) + .join('\n --- \n'); + } + + return get(hit._source, path, ''); }; From b169a9c729e71aa7d865dad5f87852c77941d5a4 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Tue, 18 Jun 2024 17:54:29 +0200 Subject: [PATCH 060/127] [Security Solution] Add missing alerts (signals) API endpoints OpenAPI specs (#184838) **Addresses:** https://github.com/elastic/kibana/issues/183661 ## Summary This PR adds missing OpenAPI specs for the following API endpoints (Alerts API and Alerts Migration API) available in both Serverless and ESS - `POST /api/detection_engine/signals/status` - `POST /api/detection_engine/signals/tags` - `POST /api/detection_engine/signals/search` and API endpoints available only in ESS - `POST /api/detection_engine/signals/migration_status` - `POST /api/detection_engine/signals/migration` - `POST /api/detection_engine/signals/finalize_migration` - `DELETE /api/detection_engine/signals/migration` **Note:** Code generation is enabled for the added specs to verify that it works and produces expected results. Generated Zod schemas and types aren't integrated in the route's code. --- .../api/detection_engine/alert_tags/index.ts | 2 +- .../set_alert_tags/set_alert_tags.gen.ts | 38 +++++ .../set_alert_tags/set_alert_tags.schema.yaml | 70 +++++++++ .../set_alert_tags_route.mock.ts | 4 +- .../set_alert_tags/set_alert_tags_route.ts | 20 --- .../api/detection_engine/signals/index.ts | 5 +- .../query_signals/query_signals_route.gen.ts | 45 ++++++ .../query_signals_route.schema.yaml | 93 ++++++++++++ .../query_signals/query_signals_route.test.ts | 140 ------------------ .../query_signals/query_signals_route.ts | 25 ---- .../set_signal_status_route.test.ts | 83 ----------- .../set_signal_status_route.ts | 24 --- .../set_signal_status_type_dependents.test.ts | 47 ------ .../set_signal_status_type_dependents.ts | 22 --- .../set_signals_status_route.gen.ts | 43 ++++++ .../set_signals_status_route.schema.yaml | 81 ++++++++++ .../create_signals_migration.gen.ts | 64 ++++++++ .../create_signals_migration.schema.yaml | 120 +++++++++++++++ .../create_signals_migration_route.mock.ts | 4 +- .../create_signals_migration_route.ts | 29 ---- .../delete_signals_migration.gen.ts | 44 ++++++ .../delete_signals_migration.schema.yaml | 100 +++++++++++++ .../delete_signals_migration_route.ts | 14 -- .../finalize_signals_migration.gen.ts | 45 ++++++ .../finalize_signals_migration.schema.yaml | 101 +++++++++++++ .../finalize_signals_migration_route.mock.ts | 4 +- .../finalize_signals_migration_route.ts | 16 -- .../get_signals_migration_status.gen.ts | 61 ++++++++ .../get_signals_migration_status.schema.yaml | 114 ++++++++++++++ ...get_signals_migration_status_route.mock.ts | 4 +- .../get_signals_migration_status_route.ts | 18 --- .../signals_migration/index.ts | 8 +- .../common/api/model/alert.gen.ts | 11 ++ .../common/api/model/alert.schema.yaml | 16 ++ .../common/api/model/error_responses.gen.ts | 30 ++++ .../api/model/error_responses.schema.yaml | 32 ++++ .../migrations/create_migration.ts | 6 +- .../migrations/migration_service.ts | 4 +- .../routes/__mocks__/request_responses.ts | 23 +-- .../create_signals_migration_route.test.ts | 4 +- .../signals/create_signals_migration_route.ts | 8 +- .../signals/delete_signals_migration_route.ts | 8 +- .../finalize_signals_migration_route.ts | 8 +- .../get_signals_migration_status_route.ts | 8 +- .../routes/signals/open_close_signals.test.ts | 22 +-- .../signals/open_close_signals_route.ts | 40 +++-- .../routes/signals/query_signals_route.ts | 14 +- .../signals/set_alert_tags_route.test.ts | 15 +- .../routes/signals/set_alert_tags_route.ts | 10 +- .../services/security_solution_api.gen.ts | 98 ++++++++++++ .../migrations/create_alerts_migrations.ts | 13 +- .../field_aliases.ts | 5 +- .../query_alerts.ts | 8 +- .../set_alert_tags.ts | 19 +-- .../utils/alerts/set_alert_tags.ts | 4 +- 55 files changed, 1325 insertions(+), 569 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.test.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.test.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.test.ts delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.schema.yaml create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration_route.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.ts create mode 100644 x-pack/plugins/security_solution/common/api/model/error_responses.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/model/error_responses.schema.yaml diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/index.ts b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/index.ts index 7adc565a09c8e..0e4f6a7ae6609 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/index.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './set_alert_tags/set_alert_tags_route'; +export * from './set_alert_tags/set_alert_tags.gen'; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.gen.ts new file mode 100644 index 0000000000000..3640d78cd33b2 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Manage alert tags API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { AlertIds, AlertTags } from '../../../model/alert.gen'; + +export type ManageAlertTags = z.infer; +export const ManageAlertTags = z.object({ + tags_to_add: AlertTags, + tags_to_remove: AlertTags, +}); + +export type ManageAlertTagsRequestBody = z.infer; +export const ManageAlertTagsRequestBody = z.object({ + ids: AlertIds, + tags: ManageAlertTags, +}); +export type ManageAlertTagsRequestBodyInput = z.input; + +/** + * Elasticsearch update by query response + */ +export type ManageAlertTagsResponse = z.infer; +export const ManageAlertTagsResponse = z.object({}).catchall(z.unknown()); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.schema.yaml new file mode 100644 index 0000000000000..ca2c93b88b25e --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.schema.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.0 +info: + title: Manage alert tags API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/tags: + post: + x-labels: [serverless, ess] + operationId: ManageAlertTags + x-codegen-enabled: true + summary: Manage alert tags for a one or more alerts + tags: + - Alerts API + requestBody: + description: An object containing tags to add or remove and alert ids the changes will be applied + required: true + content: + application/json: + schema: + type: object + properties: + ids: + $ref: '../../../model/alert.schema.yaml#/components/schemas/AlertIds' + tags: + $ref: '#/components/schemas/ManageAlertTags' + required: + - ids + - tags + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + additionalProperties: true + description: Elasticsearch update by query response + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + ManageAlertTags: + type: object + properties: + tags_to_add: + $ref: '../../../model/alert.schema.yaml#/components/schemas/AlertTags' + tags_to_remove: + $ref: '../../../model/alert.schema.yaml#/components/schemas/AlertTags' + required: + - tags_to_add + - tags_to_remove diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.mock.ts b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.mock.ts index f1e05ad7f125a..a14b36fb7b2c5 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.mock.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.mock.ts @@ -5,13 +5,13 @@ * 2.0. */ -import type { SetAlertTagsRequestBody } from './set_alert_tags_route'; +import type { ManageAlertTagsRequestBody } from './set_alert_tags.gen'; export const getSetAlertTagsRequestMock = ( tagsToAdd: string[] = [], tagsToRemove: string[] = [], ids: string[] = [] -): SetAlertTagsRequestBody => ({ +): ManageAlertTagsRequestBody => ({ tags: { tags_to_add: tagsToAdd, tags_to_remove: tagsToRemove }, ids, }); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.ts deleted file mode 100644 index 8a6f93c20b770..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags_route.ts +++ /dev/null @@ -1,20 +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 * as t from 'io-ts'; - -import { alert_tag_ids, alert_tags } from '../../model'; - -export const setAlertTagsRequestBody = t.exact( - t.type({ - tags: alert_tags, - ids: alert_tag_ids, - }) -); - -export type SetAlertTagsRequestBody = t.TypeOf; -export type SetAlertTagsRequestBodyDecoded = SetAlertTagsRequestBody; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/index.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/index.ts index 636728ee2525d..97f441030bb48 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/index.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals/index.ts @@ -5,6 +5,5 @@ * 2.0. */ -export * from './query_signals/query_signals_route'; -export * from './set_signal_status/set_signal_status_route'; -export * from './set_signal_status/set_signal_status_type_dependents'; +export * from './query_signals/query_signals_route.gen'; +export * from './set_signal_status/set_signals_status_route.gen'; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.gen.ts new file mode 100644 index 0000000000000..67c5a695d1949 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Alerts search API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type AlertsSortCombinations = z.infer; +export const AlertsSortCombinations = z.union([z.string(), z.object({}).catchall(z.unknown())]); + +export type AlertsSort = z.infer; +export const AlertsSort = z.union([AlertsSortCombinations, z.array(AlertsSortCombinations)]); + +/** + * Elasticsearch query and aggregation request + */ +export type SearchAlertsRequestBody = z.infer; +export const SearchAlertsRequestBody = z.object({ + query: z.object({}).catchall(z.unknown()).optional(), + aggs: z.object({}).catchall(z.unknown()).optional(), + size: z.number().int().min(0).optional(), + track_total_hits: z.boolean().optional(), + _source: z.union([z.boolean(), z.string(), z.array(z.string())]).optional(), + fields: z.array(z.string()).optional(), + runtime_mappings: z.object({}).catchall(z.unknown()).optional(), + sort: AlertsSort.optional(), +}); +export type SearchAlertsRequestBodyInput = z.input; + +/** + * Elasticsearch search response + */ +export type SearchAlertsResponse = z.infer; +export const SearchAlertsResponse = z.object({}).catchall(z.unknown()); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.schema.yaml new file mode 100644 index 0000000000000..cd70e4b0c4071 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.schema.yaml @@ -0,0 +1,93 @@ +openapi: 3.0.0 +info: + title: Alerts search API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/search: + post: + x-labels: [serverless, ess] + operationId: SearchAlerts + x-codegen-enabled: true + summary: Find and/or aggregate detection alerts that match the given query + tags: + - Alerts API + requestBody: + description: Search and/or aggregation query + required: true + content: + application/json: + schema: + type: object + properties: + query: + type: object + additionalProperties: true + aggs: + type: object + additionalProperties: true + size: + type: integer + minimum: 0 + track_total_hits: + type: boolean + _source: + oneOf: + - type: boolean + - type: string + - type: array + items: + type: string + fields: + type: array + items: + type: string + runtime_mappings: + type: object + additionalProperties: true + sort: + $ref: '#/components/schemas/AlertsSort' + description: Elasticsearch query and aggregation request + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + additionalProperties: true + description: Elasticsearch search response + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + AlertsSortCombinations: + anyOf: + - type: string + - type: object + additionalProperties: true + + AlertsSort: + oneOf: + - $ref: '#/components/schemas/AlertsSortCombinations' + - type: array + items: + $ref: '#/components/schemas/AlertsSortCombinations' diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.test.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.test.ts deleted file mode 100644 index 6afdc9a07e8ab..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { QuerySignalsSchema } from './query_signals_route'; -import { querySignalsSchema } from './query_signals_route'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -describe('query, aggs, size, _source and track_total_hits on signals index', () => { - test('query, aggs, size, _source and track_total_hits simultaneously', () => { - const payload: QuerySignalsSchema = { - query: {}, - aggs: {}, - size: 1, - track_total_hits: true, - _source: ['field'], - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('query, only', () => { - const payload: QuerySignalsSchema = { - query: {}, - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('aggs only', () => { - const payload: QuerySignalsSchema = { - aggs: {}, - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('size only', () => { - const payload: QuerySignalsSchema = { - size: 1, - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('track_total_hits only', () => { - const payload: QuerySignalsSchema = { - track_total_hits: true, - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('_source only (as string)', () => { - const payload: QuerySignalsSchema = { - _source: 'field', - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('_source only (as string[])', () => { - const payload: QuerySignalsSchema = { - _source: ['field'], - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('_source only (as boolean)', () => { - const payload: QuerySignalsSchema = { - _source: false, - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('fields only', () => { - const payload: QuerySignalsSchema = { - fields: ['test*'], - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('sort only', () => { - const payload: QuerySignalsSchema = { - sort: { - '@payload': 'desc', - }, - }; - - const decoded = querySignalsSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); -}); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.ts deleted file mode 100644 index 7c0283f3f2a80..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/query_signals/query_signals_route.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; -import { PositiveInteger } from '@kbn/securitysolution-io-ts-types'; - -export const querySignalsSchema = t.exact( - t.partial({ - query: t.object, - aggs: t.object, - size: PositiveInteger, - track_total_hits: t.boolean, - _source: t.union([t.boolean, t.string, t.array(t.string)]), - fields: t.array(t.string), - runtime_mappings: t.unknown, - sort: t.object, - }) -); - -export type QuerySignalsSchema = t.TypeOf; -export type QuerySignalsSchemaDecoded = QuerySignalsSchema; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.test.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.test.ts deleted file mode 100644 index 3f9e432fbc4f9..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.test.ts +++ /dev/null @@ -1,83 +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 { SetSignalsStatusSchema } from './set_signal_status_route'; -import { setSignalsStatusSchema } from './set_signal_status_route'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { left } from 'fp-ts/lib/Either'; - -describe('set signal status schema', () => { - test('signal_ids and status is valid', () => { - const payload: SetSignalsStatusSchema = { - signal_ids: ['somefakeid'], - status: 'open', - }; - - const decoded = setSignalsStatusSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('query and status is valid', () => { - const payload: SetSignalsStatusSchema = { - query: {}, - status: 'open', - }; - - const decoded = setSignalsStatusSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('signal_ids and missing status is invalid', () => { - const payload: Omit = { - signal_ids: ['somefakeid'], - }; - - const decoded = setSignalsStatusSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "status"', - ]); - expect(message.schema).toEqual({}); - }); - - test('query and missing status is invalid', () => { - const payload: Omit = { - query: {}, - }; - - const decoded = setSignalsStatusSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "status"', - ]); - expect(message.schema).toEqual({}); - }); - - test('signal_ids is present but status has wrong value', () => { - const payload: Omit & { status: 'fakeVal' } = { - query: {}, - status: 'fakeVal', - }; - - const decoded = setSignalsStatusSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "fakeVal" supplied to "status"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.ts deleted file mode 100644 index 78d62031d5eb3..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_route.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; - -import { conflicts, signal_ids, signal_status_query, status } from '../../model'; - -export const setSignalsStatusSchema = t.intersection([ - t.type({ - status, - }), - t.partial({ - conflicts, - signal_ids, - query: signal_status_query, - }), -]); - -export type SetSignalsStatusSchema = t.TypeOf; -export type SetSignalsStatusSchemaDecoded = SetSignalsStatusSchema; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.test.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.test.ts deleted file mode 100644 index 97cf74435c294..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { setSignalStatusValidateTypeDependents } from './set_signal_status_type_dependents'; -import type { SetSignalsStatusSchema } from './set_signal_status_route'; - -describe('update_rules_type_dependents', () => { - test('You can have just a "signals_id"', () => { - const schema: SetSignalsStatusSchema = { - status: 'open', - signal_ids: ['some-id'], - }; - const errors = setSignalStatusValidateTypeDependents(schema); - expect(errors).toEqual([]); - }); - - test('You can have just a "query"', () => { - const schema: SetSignalsStatusSchema = { - status: 'open', - query: {}, - }; - const errors = setSignalStatusValidateTypeDependents(schema); - expect(errors).toEqual([]); - }); - - test('You cannot have both a "signals_id" and a "query"', () => { - const schema: SetSignalsStatusSchema = { - status: 'open', - query: {}, - signal_ids: ['some-id'], - }; - const errors = setSignalStatusValidateTypeDependents(schema); - expect(errors).toEqual(['both "signal_ids" and "query" cannot exist, choose one or the other']); - }); - - test('You must set either an "signals_id" and a "query"', () => { - const schema: SetSignalsStatusSchema = { - status: 'open', - }; - const errors = setSignalStatusValidateTypeDependents(schema); - expect(errors).toEqual(['either "signal_ids" or "query" must be set']); - }); -}); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.ts deleted file mode 100644 index a484fde33d107..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signal_status_type_dependents.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { SetSignalsStatusSchema } from './set_signal_status_route'; - -export const validateId = (signalStatus: SetSignalsStatusSchema): string[] => { - if (signalStatus.signal_ids != null && signalStatus.query != null) { - return ['both "signal_ids" and "query" cannot exist, choose one or the other']; - } else if (signalStatus.signal_ids == null && signalStatus.query == null) { - return ['either "signal_ids" or "query" must be set']; - } else { - return []; - } -}; - -export const setSignalStatusValidateTypeDependents = (schema: SetSignalsStatusSchema): string[] => { - return [...validateId(schema)]; -}; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen.ts new file mode 100644 index 0000000000000..a64a35d16d83e --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Set alerts status API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '../../../model/primitives.gen'; +import { AlertStatus } from '../../../model/alert.gen'; + +export type SetAlertsStatusByIds = z.infer; +export const SetAlertsStatusByIds = z.object({ + signal_ids: z.array(NonEmptyString).min(1), + status: AlertStatus, +}); + +export type SetAlertsStatusByQuery = z.infer; +export const SetAlertsStatusByQuery = z.object({ + query: z.object({}).catchall(z.unknown()), + status: AlertStatus, + conflicts: z.enum(['abort', 'proceed']).optional().default('abort'), +}); + +export type SetAlertsStatusRequestBody = z.infer; +export const SetAlertsStatusRequestBody = z.union([SetAlertsStatusByIds, SetAlertsStatusByQuery]); +export type SetAlertsStatusRequestBodyInput = z.input; + +/** + * Elasticsearch update by query response + */ +export type SetAlertsStatusResponse = z.infer; +export const SetAlertsStatusResponse = z.object({}).catchall(z.unknown()); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.schema.yaml new file mode 100644 index 0000000000000..29ee065c77e6b --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.schema.yaml @@ -0,0 +1,81 @@ +openapi: 3.0.0 +info: + title: Set alerts status API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/status: + post: + x-labels: [serverless, ess] + operationId: SetAlertsStatus + x-codegen-enabled: true + summary: Sets the status of one or more alerts + tags: + - Alerts API + requestBody: + description: An object containing desired status and explicit alert ids or a query to select alerts + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SetAlertsStatusByIds' + - $ref: '#/components/schemas/SetAlertsStatusByQuery' + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + additionalProperties: true + description: Elasticsearch update by query response + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + SetAlertsStatusByIds: + type: object + properties: + signal_ids: + type: array + items: + $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + minItems: 1 + status: + $ref: '../../../model/alert.schema.yaml#/components/schemas/AlertStatus' + required: [signal_ids, status] + + SetAlertsStatusByQuery: + type: object + properties: + query: + type: object + additionalProperties: true + status: + $ref: '../../../model/alert.schema.yaml#/components/schemas/AlertStatus' + conflicts: + type: string + enum: + - abort + - proceed + default: abort + required: [query, status] diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.gen.ts new file mode 100644 index 0000000000000..f82dedc27a289 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.gen.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Initiates alerts migration API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '../../../model/primitives.gen'; + +export type AlertsReindexOptions = z.infer; +export const AlertsReindexOptions = z.object({ + requests_per_second: z.number().int().min(1).optional(), + size: z.number().int().min(1).optional(), + slices: z.number().int().min(1).optional(), +}); + +export type AlertsIndexMigrationSuccess = z.infer; +export const AlertsIndexMigrationSuccess = z.object({ + index: z.string(), + migration_id: z.string(), + migration_index: z.string(), +}); + +export type AlertsIndexMigrationError = z.infer; +export const AlertsIndexMigrationError = z.object({ + index: z.string(), + error: z.object({ + message: z.string(), + status_code: z.string(), + }), +}); + +export type SkippedAlertsIndexMigration = z.infer; +export const SkippedAlertsIndexMigration = z.object({ + index: z.string(), +}); + +export type CreateAlertsMigrationRequestBody = z.infer; +export const CreateAlertsMigrationRequestBody = z + .object({ + index: z.array(NonEmptyString).min(1), + }) + .merge(AlertsReindexOptions); +export type CreateAlertsMigrationRequestBodyInput = z.input< + typeof CreateAlertsMigrationRequestBody +>; + +export type CreateAlertsMigrationResponse = z.infer; +export const CreateAlertsMigrationResponse = z.object({ + indices: z.array( + z.union([AlertsIndexMigrationSuccess, AlertsIndexMigrationError, SkippedAlertsIndexMigration]) + ), +}); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.schema.yaml new file mode 100644 index 0000000000000..26204ea0d6195 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.schema.yaml @@ -0,0 +1,120 @@ +openapi: 3.0.0 +info: + title: Initiates alerts migration API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/migration: + post: + x-labels: [ess] + operationId: CreateAlertsMigration + x-codegen-enabled: true + summary: Initiates an alerts migration + tags: + - Alerts migration API + requestBody: + description: Alerts migration parameters + required: true + content: + application/json: + schema: + allOf: + - type: object + properties: + index: + type: array + items: + $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + minItems: 1 + required: [index] + - $ref: '#/components/schemas/AlertsReindexOptions' + + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + indices: + type: array + items: + oneOf: + - $ref: '#/components/schemas/AlertsIndexMigrationSuccess' + - $ref: '#/components/schemas/AlertsIndexMigrationError' + - $ref: '#/components/schemas/SkippedAlertsIndexMigration' + required: [indices] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + AlertsReindexOptions: + type: object + properties: + requests_per_second: + type: integer + minimum: 1 + size: + type: integer + minimum: 1 + slices: + type: integer + minimum: 1 + + AlertsIndexMigrationSuccess: + type: object + properties: + index: + type: string + migration_id: + type: string + migration_index: + type: string + required: + - index + - migration_id + - migration_index + + AlertsIndexMigrationError: + type: object + properties: + index: + type: string + error: + type: object + properties: + message: + type: string + status_code: + type: string + required: [message, status_code] + required: + - index + - error + + SkippedAlertsIndexMigration: + type: object + properties: + index: + type: string + required: + - index diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.mock.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.mock.ts index ccb5543ef72d2..09a94fc86224c 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.mock.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.mock.ts @@ -5,10 +5,10 @@ * 2.0. */ -import type { CreateSignalsMigrationSchema } from './create_signals_migration_route'; +import type { CreateAlertsMigrationRequestBody } from './create_signals_migration.gen'; export const getCreateSignalsMigrationSchemaMock = ( index: string = 'signals-index' -): CreateSignalsMigrationSchema => ({ +): CreateAlertsMigrationRequestBody => ({ index: [index], }); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.ts deleted file mode 100644 index 9089efeb87d05..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; - -import { PositiveInteger, PositiveIntegerGreaterThanZero } from '@kbn/securitysolution-io-ts-types'; - -export const signalsReindexOptions = t.partial({ - requests_per_second: t.number, - size: PositiveIntegerGreaterThanZero, - slices: PositiveInteger, -}); - -export type SignalsReindexOptions = t.TypeOf; - -export const createSignalsMigrationSchema = t.intersection([ - t.exact( - t.type({ - index: t.array(t.string), - }) - ), - t.exact(signalsReindexOptions), -]); - -export type CreateSignalsMigrationSchema = t.TypeOf; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.gen.ts new file mode 100644 index 0000000000000..c82407052c972 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.gen.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Alerts migration cleanup API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type MigrationCleanupResult = z.infer; +export const MigrationCleanupResult = z.object({ + id: z.string(), + destinationIndex: z.string(), + status: z.enum(['success', 'failure', 'pending']), + sourceIndex: z.string(), + version: z.string(), + updated: z.string().datetime(), + error: z + .object({ + message: z.string(), + status_code: z.number().int(), + }) + .optional(), +}); + +export type AlertsMigrationCleanupRequestBody = z.infer; +export const AlertsMigrationCleanupRequestBody = z.object({ + migration_ids: z.array(z.string()).min(1), +}); +export type AlertsMigrationCleanupRequestBodyInput = z.input< + typeof AlertsMigrationCleanupRequestBody +>; + +export type AlertsMigrationCleanupResponse = z.infer; +export const AlertsMigrationCleanupResponse = z.array(MigrationCleanupResult); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.schema.yaml new file mode 100644 index 0000000000000..7b8136f3702cf --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.schema.yaml @@ -0,0 +1,100 @@ +openapi: 3.0.0 +info: + title: Alerts migration cleanup API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/migration: + delete: + x-labels: [ess] + operationId: AlertsMigrationCleanup + x-codegen-enabled: true + summary: Performs alerts migration(s) cleanup + description: | + Migrations favor data integrity over shard size. Consequently, unused or orphaned indices are artifacts of + the migration process. A successful migration will result in both the old and new indices being present. + As such, the old, orphaned index can (and likely should) be deleted. While you can delete these indices manually, + the endpoint accomplishes this task by applying a deletion policy to the relevant index, causing it to be deleted + after 30 days. It also deletes other artifacts specific to the migration implementation. + tags: + - Alerts migration API + requestBody: + description: Array of `migration_id`s to cleanup + required: true + content: + application/json: + schema: + type: object + properties: + migration_ids: + type: array + items: + type: string + minItems: 1 + required: [migration_ids] + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/MigrationCleanupResult' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + MigrationCleanupResult: + type: object + properties: + id: + type: string + destinationIndex: + type: string + status: + type: string + enum: + - success + - failure + - pending + sourceIndex: + type: string + version: + type: string + updated: + type: string + format: date-time + error: + type: object + properties: + message: + type: string + status_code: + type: integer + required: [message, status_code] + required: + - id + - destinationIndex + - status + - sourceIndex + - version + - updated diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration_route.ts deleted file mode 100644 index 837f34f3ec14f..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration_route.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; - -export const deleteSignalsMigrationSchema = t.exact( - t.type({ - migration_ids: t.array(t.string), - }) -); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen.ts new file mode 100644 index 0000000000000..cd18cad8e1cfa --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Finalize alerts migration API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type MigrationFinalizationResult = z.infer; +export const MigrationFinalizationResult = z.object({ + id: z.string(), + completed: z.boolean(), + destinationIndex: z.string(), + status: z.enum(['success', 'failure', 'pending']), + sourceIndex: z.string(), + version: z.string(), + updated: z.string().datetime(), + error: z + .object({ + message: z.string(), + status_code: z.number().int(), + }) + .optional(), +}); + +export type FinalizeAlertsMigrationRequestBody = z.infer; +export const FinalizeAlertsMigrationRequestBody = z.object({ + migration_ids: z.array(z.string()).min(1), +}); +export type FinalizeAlertsMigrationRequestBodyInput = z.input< + typeof FinalizeAlertsMigrationRequestBody +>; + +export type FinalizeAlertsMigrationResponse = z.infer; +export const FinalizeAlertsMigrationResponse = z.array(MigrationFinalizationResult); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.schema.yaml new file mode 100644 index 0000000000000..3654973f9de7e --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.schema.yaml @@ -0,0 +1,101 @@ +openapi: 3.0.0 +info: + title: Finalize alerts migration API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/finalize_migration: + post: + x-labels: [ess] + operationId: FinalizeAlertsMigration + x-codegen-enabled: true + summary: Finalizes alerts migration(s) + description: | + The finalization endpoint replaces the original index's alias with the successfully migrated index's alias. + The endpoint is idempotent; therefore, it can safely be used to poll a given migration and, upon completion, + finalize it. + tags: + - Alerts migration API + requestBody: + description: Array of `migration_id`s to finalize + required: true + content: + application/json: + schema: + type: object + properties: + migration_ids: + type: array + items: + type: string + minItems: 1 + required: [migration_ids] + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/MigrationFinalizationResult' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + MigrationFinalizationResult: + type: object + properties: + id: + type: string + completed: + type: boolean + destinationIndex: + type: string + status: + type: string + enum: + - success + - failure + - pending + sourceIndex: + type: string + version: + type: string + updated: + type: string + format: date-time + error: + type: object + properties: + message: + type: string + status_code: + type: integer + required: [message, status_code] + required: + - id + - completed + - destinationIndex + - status + - sourceIndex + - version + - updated diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.mock.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.mock.ts index 25d66c5b68d09..b43a04819e67f 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.mock.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.mock.ts @@ -5,8 +5,8 @@ * 2.0. */ -import type { FinalizeSignalsMigrationSchema } from './finalize_signals_migration_route'; +import type { FinalizeAlertsMigrationRequestBody } from './finalize_signals_migration.gen'; -export const getFinalizeSignalsMigrationSchemaMock = (): FinalizeSignalsMigrationSchema => ({ +export const getFinalizeSignalsMigrationSchemaMock = (): FinalizeAlertsMigrationRequestBody => ({ migration_ids: ['migrationSOIdentifier'], }); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.ts deleted file mode 100644 index a4a48a7bc0c21..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration_route.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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; - -export const finalizeSignalsMigrationSchema = t.exact( - t.type({ - migration_ids: t.array(t.string), - }) -); - -export type FinalizeSignalsMigrationSchema = t.TypeOf; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.gen.ts new file mode 100644 index 0000000000000..acf9c9edd389d --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.gen.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Get alerts migration status API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; +import { isValidDateMath } from '@kbn/zod-helpers'; + +import { NonEmptyString } from '../../../model/primitives.gen'; + +export type AlertVersion = z.infer; +export const AlertVersion = z.object({ + version: z.number().int(), + count: z.number().int(), +}); + +export type MigrationStatus = z.infer; +export const MigrationStatus = z.object({ + id: NonEmptyString, + status: z.enum(['success', 'failure', 'pending']), + version: z.number().int(), + updated: z.string().datetime(), +}); + +export type IndexMigrationStatus = z.infer; +export const IndexMigrationStatus = z.object({ + index: NonEmptyString, + version: z.number().int(), + signal_versions: z.array(AlertVersion), + migrations: z.array(MigrationStatus), + is_outdated: z.boolean(), +}); + +export type GetAlertsMigrationStatusRequestQuery = z.infer< + typeof GetAlertsMigrationStatusRequestQuery +>; +export const GetAlertsMigrationStatusRequestQuery = z.object({ + /** + * Maximum age of qualifying detection alerts + */ + from: z.string().superRefine(isValidDateMath), +}); +export type GetAlertsMigrationStatusRequestQueryInput = z.input< + typeof GetAlertsMigrationStatusRequestQuery +>; + +export type GetAlertsMigrationStatusResponse = z.infer; +export const GetAlertsMigrationStatusResponse = z.object({ + indices: z.array(IndexMigrationStatus), +}); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.schema.yaml new file mode 100644 index 0000000000000..b480b4374498b --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.schema.yaml @@ -0,0 +1,114 @@ +openapi: 3.0.0 +info: + title: Get alerts migration status API endpoint + version: '2023-10-31' +paths: + /api/detection_engine/signals/migration_status: + post: + x-labels: [ess] + operationId: GetAlertsMigrationStatus + x-codegen-enabled: true + summary: Returns an alerts migration status + tags: + - Alerts migration API + parameters: + - name: from + in: query + description: Maximum age of qualifying detection alerts + required: true + schema: + type: string + description: | + Time from which data is analyzed. For example, now-4200s means the rule analyzes data from 70 minutes + before its start time. Defaults to now-6m (analyzes data from 6 minutes before the start time). + format: date-math + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + indices: + type: array + items: + $ref: '#/components/schemas/IndexMigrationStatus' + required: [indices] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + AlertVersion: + type: object + properties: + version: + type: integer + count: + type: integer + required: [version, count] + + MigrationStatus: + type: object + properties: + id: + $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + status: + type: string + enum: + - success + - failure + - pending + version: + type: integer + updated: + type: string + format: date-time + required: + - id + - status + - version + - updated + + IndexMigrationStatus: + type: object + properties: + index: + $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + version: + type: integer + signal_versions: + type: array + items: + $ref: '#/components/schemas/AlertVersion' + migrations: + type: array + items: + $ref: '#/components/schemas/MigrationStatus' + is_outdated: + type: boolean + required: + - index + - version + - signal_versions + - migrations + - is_outdated diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.mock.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.mock.ts index 8cc78ffa9700e..968d72d6f40d0 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.mock.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.mock.ts @@ -5,8 +5,8 @@ * 2.0. */ -import type { GetSignalsMigrationStatusSchema } from './get_signals_migration_status_route'; +import type { GetAlertsMigrationStatusRequestQuery } from './get_signals_migration_status.gen'; -export const getSignalsMigrationStatusSchemaMock = (): GetSignalsMigrationStatusSchema => ({ +export const getSignalsMigrationStatusSchemaMock = (): GetAlertsMigrationStatusRequestQuery => ({ from: 'now-30d', }); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.ts deleted file mode 100644 index f2a9fc210df2b..0000000000000 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status_route.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; - -import { RuleIntervalFrom } from '@kbn/securitysolution-io-ts-alerting-types'; - -export const getSignalsMigrationStatusSchema = t.exact( - t.type({ - from: RuleIntervalFrom, - }) -); - -export type GetSignalsMigrationStatusSchema = t.TypeOf; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/index.ts b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/index.ts index 78452dc62f46c..84b00fc9f297c 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/index.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/signals_migration/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -export * from './create_signals_migration/create_signals_migration_route'; -export * from './delete_signals_migration/delete_signals_migration_route'; -export * from './finalize_signals_migration/finalize_signals_migration_route'; -export * from './get_signals_migration_status/get_signals_migration_status_route'; +export * from './create_signals_migration/create_signals_migration.gen'; +export * from './delete_signals_migration/delete_signals_migration.gen'; +export * from './finalize_signals_migration/finalize_signals_migration.gen'; +export * from './get_signals_migration_status/get_signals_migration_status.gen'; diff --git a/x-pack/plugins/security_solution/common/api/model/alert.gen.ts b/x-pack/plugins/security_solution/common/api/model/alert.gen.ts index 19ebcf2dee734..d149d36ab64b8 100644 --- a/x-pack/plugins/security_solution/common/api/model/alert.gen.ts +++ b/x-pack/plugins/security_solution/common/api/model/alert.gen.ts @@ -23,3 +23,14 @@ import { NonEmptyString } from './primitives.gen'; */ export type AlertIds = z.infer; export const AlertIds = z.array(NonEmptyString).min(1); + +export type AlertTag = z.infer; +export const AlertTag = NonEmptyString; + +export type AlertTags = z.infer; +export const AlertTags = z.array(AlertTag); + +export type AlertStatus = z.infer; +export const AlertStatus = z.enum(['open', 'closed', 'acknowledged', 'in-progress']); +export type AlertStatusEnum = typeof AlertStatus.enum; +export const AlertStatusEnum = AlertStatus.enum; diff --git a/x-pack/plugins/security_solution/common/api/model/alert.schema.yaml b/x-pack/plugins/security_solution/common/api/model/alert.schema.yaml index f28508dc620f2..ecf7e02d6ebe3 100644 --- a/x-pack/plugins/security_solution/common/api/model/alert.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/model/alert.schema.yaml @@ -12,3 +12,19 @@ components: $ref: './primitives.schema.yaml#/components/schemas/NonEmptyString' minItems: 1 description: A list of alerts ids. + + AlertTag: + $ref: './primitives.schema.yaml#/components/schemas/NonEmptyString' + + AlertTags: + type: array + items: + $ref: '#/components/schemas/AlertTag' + + AlertStatus: + type: string + enum: + - open + - closed + - acknowledged + - in-progress diff --git a/x-pack/plugins/security_solution/common/api/model/error_responses.gen.ts b/x-pack/plugins/security_solution/common/api/model/error_responses.gen.ts new file mode 100644 index 0000000000000..17d2c59bd338f --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/model/error_responses.gen.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Error Schema + * version: not applicable + */ + +import { z } from 'zod'; + +export type PlatformErrorResponse = z.infer; +export const PlatformErrorResponse = z.object({ + statusCode: z.number().int(), + error: z.string(), + message: z.string(), +}); + +export type SiemErrorResponse = z.infer; +export const SiemErrorResponse = z.object({ + status_code: z.number().int(), + message: z.string(), +}); diff --git a/x-pack/plugins/security_solution/common/api/model/error_responses.schema.yaml b/x-pack/plugins/security_solution/common/api/model/error_responses.schema.yaml new file mode 100644 index 0000000000000..8f0891f3f574f --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/model/error_responses.schema.yaml @@ -0,0 +1,32 @@ +openapi: 3.0.0 +info: + title: Error Schema + version: 'not applicable' +paths: {} +components: + x-codegen-enabled: true + schemas: + PlatformErrorResponse: + type: object + properties: + statusCode: + type: integer + error: + type: string + message: + type: string + required: + - statusCode + - error + - message + + SiemErrorResponse: + type: object + properties: + status_code: + type: integer + message: + type: string + required: + - status_code + - message diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts index da49cda43507a..8bc38b1ecdf94 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts @@ -6,7 +6,7 @@ */ import type { ElasticsearchClient } from '@kbn/core/server'; -import type { SignalsReindexOptions } from '../../../../common/api/detection_engine/signals_migration'; +import type { AlertsReindexOptions } from '../../../../common/api/detection_engine/signals_migration'; import { createMigrationIndex } from './create_migration_index'; export interface CreatedMigration { @@ -24,7 +24,7 @@ export interface CreatedMigration { * @param esClient An {@link ElasticsearchClient} * @param index name of the concrete signals index to be migrated * @param version version of the current signals template/mappings - * @param reindexOptions object containing reindex options {@link SignalsReindexOptions} + * @param reindexOptions object containing reindex options {@link AlertsReindexOptions} * * @returns identifying information representing the {@link MigrationInfo} * @throws if elasticsearch returns an error @@ -37,7 +37,7 @@ export const createMigration = async ({ }: { esClient: ElasticsearchClient; index: string; - reindexOptions: SignalsReindexOptions; + reindexOptions: AlertsReindexOptions; version: number; }): Promise => { const migrationIndex = await createMigrationIndex({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_service.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_service.ts index e0c82f70549fd..5a4399bd6389c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_service.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_service.ts @@ -6,7 +6,7 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; -import type { SignalsReindexOptions } from '../../../../common/api/detection_engine/signals_migration'; +import type { AlertsReindexOptions } from '../../../../common/api/detection_engine/signals_migration'; import type { SignalsMigrationSO } from './saved_objects_schema'; import { createMigrationSavedObject } from './create_migration_saved_object'; import { createMigration } from './create_migration'; @@ -16,7 +16,7 @@ import { deleteMigration } from './delete_migration'; export interface CreateParams { index: string; version: number; - reindexOptions: SignalsReindexOptions; + reindexOptions: AlertsReindexOptions; } export interface FinalizeParams { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 82a40cbf71a41..2bd7efdbbdcf2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -11,6 +11,12 @@ import { ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { ruleTypeMappings } from '@kbn/securitysolution-rules'; import type { SanitizedRule, ResolvedSanitizedRule } from '@kbn/alerting-plugin/common'; +import type { + SetAlertsStatusByIds, + SetAlertsStatusByQuery, + SetAlertsStatusRequestBodyInput, + SearchAlertsRequestBody, +} from '../../../../../common/api/detection_engine/signals'; import { DETECTION_ENGINE_RULES_URL, DETECTION_ENGINE_SIGNALS_STATUS_URL, @@ -36,10 +42,7 @@ import { } from '../../../../../common/api/detection_engine/rule_management/mocks'; import { getCreateRulesSchemaMock } from '../../../../../common/api/detection_engine/model/rule_schema/mocks'; -import type { - QuerySignalsSchemaDecoded, - SetSignalsStatusSchemaDecoded, -} from '../../../../../common/api/detection_engine/signals'; + import { getFinalizeSignalsMigrationSchemaMock, getSignalsMigrationStatusSchemaMock, @@ -53,26 +56,28 @@ import { getQueryRuleParams } from '../../rule_schema/mocks'; import { requestMock } from './request'; import type { HapiReadableStream } from '../../../../types'; -export const typicalSetStatusSignalByIdsPayload = (): SetSignalsStatusSchemaDecoded => ({ +export const typicalSetStatusSignalByIdsPayload = (): SetAlertsStatusByIds => ({ signal_ids: ['somefakeid1', 'somefakeid2'], status: 'closed', }); -export const typicalSetStatusSignalByQueryPayload = (): SetSignalsStatusSchemaDecoded => ({ +export const typicalSetStatusSignalByQueryPayload = (): SetAlertsStatusByQuery => ({ query: { bool: { filter: { range: { '@timestamp': { gte: 'now-2M', lte: 'now/M' } } } } }, status: 'closed', + conflicts: 'abort', }); -export const typicalSignalsQuery = (): QuerySignalsSchemaDecoded => ({ +export const typicalSignalsQuery = (): SearchAlertsRequestBody => ({ aggs: {}, query: { match_all: {} }, }); -export const typicalSignalsQueryAggs = (): QuerySignalsSchemaDecoded => ({ +export const typicalSignalsQueryAggs = (): SearchAlertsRequestBody => ({ aggs: { statuses: { terms: { field: ALERT_WORKFLOW_STATUS, size: 10 } } }, }); -export const setStatusSignalMissingIdsAndQueryPayload = (): SetSignalsStatusSchemaDecoded => ({ +// @ts-expect-error data with missing required fields +export const setStatusSignalMissingIdsAndQueryPayload = (): SetAlertsStatusRequestBodyInput => ({ status: 'closed', }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.test.ts index e48cd6ff2dab1..5d81134325c50 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.test.ts @@ -7,7 +7,6 @@ import { requestMock, serverMock } from '../__mocks__'; import type { SetupPlugins } from '../../../../plugin'; -import type { SignalsReindexOptions } from '../../../../../common/api/detection_engine/signals_migration'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_URL } from '../../../../../common/constants'; import { getCreateSignalsMigrationSchemaMock } from '../../../../../common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration_route.mock'; import { getIndexVersionsByIndex } from '../../migrations/get_index_versions_by_index'; @@ -17,6 +16,7 @@ import { getIndexAliases } from '@kbn/securitysolution-es-utils'; import { getTemplateVersion } from '../index/check_template_version'; import { createSignalsMigrationRoute } from './create_signals_migration_route'; import { SIGNALS_TEMPLATE_VERSION } from '../index/get_signals_template'; +import type { AlertsReindexOptions } from '../../../../../common/api/detection_engine/signals_migration'; jest.mock('../index/check_template_version'); jest.mock('@kbn/securitysolution-es-utils', () => { @@ -53,7 +53,7 @@ describe('creating signals migrations route', () => { }); it('passes options to the createMigration', async () => { - const reindexOptions: SignalsReindexOptions = { requests_per_second: 4, size: 10, slices: 2 }; + const reindexOptions: AlertsReindexOptions = { requests_per_second: 4, size: 10, slices: 2 }; const request = requestMock.create({ method: 'post', path: DETECTION_ENGINE_SIGNALS_MIGRATION_URL, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts index 198a1992058fa..51e1843e9b8e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts @@ -6,11 +6,11 @@ */ import { transformError, BadRequestError, getIndexAliases } from '@kbn/securitysolution-es-utils'; +import { CreateAlertsMigrationRequestBody } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import type { SetupPlugins } from '../../../../plugin'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_URL } from '../../../../../common/constants'; -import { createSignalsMigrationSchema } from '../../../../../common/api/detection_engine/signals_migration'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../utils'; import { getTemplateVersion } from '../index/check_template_version'; @@ -35,7 +35,9 @@ export const createSignalsMigrationRoute = ( .addVersion( { version: '2023-10-31', - validate: { request: { body: buildRouteValidation(createSignalsMigrationSchema) } }, + validate: { + request: { body: buildRouteValidationWithZod(CreateAlertsMigrationRequestBody) }, + }, }, async (context, request, response) => { const siemResponse = buildSiemResponse(response); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts index 4a4a38e074c0b..c2e364e58ca5b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts @@ -6,11 +6,11 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; +import { AlertsMigrationCleanupRequestBody } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import type { SetupPlugins } from '../../../../plugin'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_URL } from '../../../../../common/constants'; -import { deleteSignalsMigrationSchema } from '../../../../../common/api/detection_engine/signals_migration'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../utils'; import { signalsMigrationService } from '../../migrations/migration_service'; @@ -31,7 +31,9 @@ export const deleteSignalsMigrationRoute = ( .addVersion( { version: '2023-10-31', - validate: { request: { body: buildRouteValidation(deleteSignalsMigrationSchema) } }, + validate: { + request: { body: buildRouteValidationWithZod(AlertsMigrationCleanupRequestBody) }, + }, }, async (context, request, response) => { const siemResponse = buildSiemResponse(response); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts index 12d6520fa52d1..bfec0f82867a6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts @@ -7,11 +7,11 @@ import { transformError, BadRequestError } from '@kbn/securitysolution-es-utils'; import type { RuleDataPluginService } from '@kbn/rule-registry-plugin/server'; +import { FinalizeAlertsMigrationRequestBody } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import type { SetupPlugins } from '../../../../plugin'; import { DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL } from '../../../../../common/constants'; -import { finalizeSignalsMigrationSchema } from '../../../../../common/api/detection_engine/signals_migration'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { isMigrationFailed, isMigrationPending } from '../../migrations/helpers'; import { signalsMigrationService } from '../../migrations/migration_service'; import { buildSiemResponse } from '../utils'; @@ -34,7 +34,9 @@ export const finalizeSignalsMigrationRoute = ( .addVersion( { version: '2023-10-31', - validate: { request: { body: buildRouteValidation(finalizeSignalsMigrationSchema) } }, + validate: { + request: { body: buildRouteValidationWithZod(FinalizeAlertsMigrationRequestBody) }, + }, }, async (context, request, response) => { const siemResponse = buildSiemResponse(response); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts index dbf6d97d4b72b..185e0c6ed6175 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts @@ -6,10 +6,10 @@ */ import { transformError, getIndexAliases } from '@kbn/securitysolution-es-utils'; +import { GetAlertsMigrationStatusRequestQuery } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL } from '../../../../../common/constants'; -import { getSignalsMigrationStatusSchema } from '../../../../../common/api/detection_engine/signals_migration'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { getIndexVersionsByIndex } from '../../migrations/get_index_versions_by_index'; import { getMigrationSavedObjectsByIndex } from '../../migrations/get_migration_saved_objects_by_index'; import { getSignalsIndicesInRange } from '../../migrations/get_signals_indices_in_range'; @@ -30,7 +30,9 @@ export const getSignalsMigrationStatusRoute = (router: SecuritySolutionPluginRou .addVersion( { version: '2023-10-31', - validate: { request: { query: buildRouteValidation(getSignalsMigrationStatusSchema) } }, + validate: { + request: { query: buildRouteValidationWithZod(GetAlertsMigrationStatusRequestQuery) }, + }, }, async (context, request, response) => { const siemResponse = buildSiemResponse(response); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals.test.ts index ece3b64ad2fbf..1b2bdb6ca1ef4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals.test.ts @@ -150,12 +150,10 @@ describe('set signal status', () => { path: DETECTION_ENGINE_SIGNALS_STATUS_URL, body: setStatusSignalMissingIdsAndQueryPayload(), }); - const response = await server.inject(request, requestContextMock.convertContext(context)); - expect(response.status).toEqual(400); - expect(response.body).toEqual({ - message: ['either "signal_ids" or "query" must be set'], - status_code: 400, - }); + + const result = server.validate(request); + + expect(result.badRequest).toHaveBeenCalled(); }); test('rejects if signal_ids but no status', async () => { @@ -167,9 +165,7 @@ describe('set signal status', () => { }); const result = server.validate(request); - expect(result.badRequest).toHaveBeenCalledWith( - 'Invalid value "undefined" supplied to "status"' - ); + expect(result.badRequest).toHaveBeenCalled(); }); test('rejects if query but no status', async () => { @@ -181,9 +177,7 @@ describe('set signal status', () => { }); const result = server.validate(request); - expect(result.badRequest).toHaveBeenCalledWith( - 'Invalid value "undefined" supplied to "status"' - ); + expect(result.badRequest).toHaveBeenCalled(); }); test('rejects if query and signal_ids but no status', async () => { @@ -199,9 +193,7 @@ describe('set signal status', () => { }); const result = server.validate(request); - expect(result.badRequest).toHaveBeenCalledWith( - 'Invalid value "undefined" supplied to "status"' - ); + expect(result.badRequest).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts index 43a1951bea4c5..3030e5fe799b6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts @@ -14,11 +14,8 @@ import { } from '@kbn/rule-data-utils'; import type { ElasticsearchClient, Logger, StartServicesAccessor } from '@kbn/core/server'; import type { AuthenticatedUser } from '@kbn/security-plugin/common'; -import { - setSignalStatusValidateTypeDependents, - setSignalsStatusSchema, -} from '../../../../../common/api/detection_engine/signals'; -import type { SetSignalsStatusSchemaDecoded } from '../../../../../common/api/detection_engine/signals'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; +import { SetAlertsStatusRequestBody } from '../../../../../common/api/detection_engine/signals'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DEFAULT_ALERTS_INDEX, @@ -28,7 +25,6 @@ import { buildSiemResponse } from '../utils'; import type { ITelemetryEventsSender } from '../../../telemetry/sender'; import { INSIGHTS_CHANNEL } from '../../../telemetry/constants'; import type { StartPlugins } from '../../../../plugin'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { getSessionIDfromKibanaRequest, createAlertStatusPayloads, @@ -53,27 +49,19 @@ export const setSignalsStatusRoute = ( version: '2023-10-31', validate: { request: { - body: buildRouteValidation< - typeof setSignalsStatusSchema, - SetSignalsStatusSchemaDecoded - >(setSignalsStatusSchema), + body: buildRouteValidationWithZod(SetAlertsStatusRequestBody), }, }, }, async (context, request, response) => { - const { conflicts, signal_ids: signalIds, query, status } = request.body; + const { status } = request.body; const core = await context.core; const securitySolution = await context.securitySolution; const esClient = core.elasticsearch.client.asCurrentUser; const siemClient = securitySolution?.getAppClient(); const siemResponse = buildSiemResponse(response); - const validationErrors = setSignalStatusValidateTypeDependents(request.body); const spaceId = securitySolution?.getSpaceId() ?? 'default'; - if (validationErrors.length) { - return siemResponse.error({ statusCode: 400, body: validationErrors }); - } - if (!siemClient) { return siemResponse.error({ statusCode: 404 }); } @@ -85,9 +73,13 @@ export const setSignalsStatusRoute = ( sender.isTelemetryOptedIn(), security?.authc.getCurrentUser(request)?.username, ]); + if (isTelemetryOptedIn && clusterId) { // Sometimes the ids are in the query not passed in the request? - const toSendAlertIds = get(query, 'bool.filter.terms._id') || signalIds; + const toSendAlertIds = + 'signal_ids' in request.body + ? request.body.signal_ids + : (get(request.body.query, 'bool.filter.terms._id') as string[]); // Get Context for Insights Payloads const sessionId = getSessionIDfromKibanaRequest(clusterId, request); if (username && toSendAlertIds && sessionId && status) { @@ -105,10 +97,15 @@ export const setSignalsStatusRoute = ( } try { - if (signalIds) { + if ('signal_ids' in request.body) { + const { signal_ids: signalIds } = request.body; + const body = await updateSignalsStatusByIds(status, signalIds, spaceId, esClient, user); + return response.ok({ body }); } else { + const { conflicts, query } = request.body; + const body = await updateSignalsStatusByQuery( status, query, @@ -117,6 +114,7 @@ export const setSignalsStatusRoute = ( esClient, user ); + return response.ok({ body }); } } catch (err) { @@ -132,7 +130,7 @@ export const setSignalsStatusRoute = ( }; const updateSignalsStatusByIds = async ( - status: SetSignalsStatusSchemaDecoded['status'], + status: SetAlertsStatusRequestBody['status'], signalsId: string[], spaceId: string, esClient: ElasticsearchClient, @@ -158,7 +156,7 @@ const updateSignalsStatusByIds = async ( * This method calls `updateByQuery` with `refresh: true` which is expensive on serverless. */ const updateSignalsStatusByQuery = async ( - status: SetSignalsStatusSchemaDecoded['status'], + status: SetAlertsStatusRequestBody['status'], query: object | undefined, options: { conflicts: 'abort' | 'proceed' }, spaceId: string, @@ -181,7 +179,7 @@ const updateSignalsStatusByQuery = async ( }); const getUpdateSignalStatusScript = ( - status: SetSignalsStatusSchemaDecoded['status'], + status: SetAlertsStatusRequestBody['status'], user: AuthenticatedUser | null ) => ({ source: `if (ctx._source['${ALERT_WORKFLOW_STATUS}'] != null && ctx._source['${ALERT_WORKFLOW_STATUS}'] != '${status}') { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts index 3bd52ebdaacda..e868c2b979018 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts @@ -8,13 +8,12 @@ import type { MappingRuntimeFields, Sort } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; +import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; +import { SearchAlertsRequestBody } from '../../../../../common/api/detection_engine/signals'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '../../../../../common/constants'; import { buildSiemResponse } from '../utils'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; - -import type { QuerySignalsSchemaDecoded } from '../../../../../common/api/detection_engine/signals'; -import { querySignalsSchema } from '../../../../../common/api/detection_engine/signals'; export const querySignalsRoute = ( router: SecuritySolutionPluginRouter, @@ -33,9 +32,7 @@ export const querySignalsRoute = ( version: '2023-10-31', validate: { request: { - body: buildRouteValidation( - querySignalsSchema - ), + body: buildRouteValidationWithZod(SearchAlertsRequestBody), }, }, }, @@ -67,8 +64,7 @@ export const querySignalsRoute = ( index: indexPattern, body: { query, - // Note: I use a spread operator to please TypeScript with aggs: { ...aggs } - aggs: { ...aggs }, + aggs: aggs as Record, _source, fields, track_total_hits, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.test.ts index ab9d79c53fc3f..eaeae10d26471 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.test.ts @@ -75,20 +75,9 @@ describe('setAlertTagsRoute', () => { body: getSetAlertTagsRequestMock(['tag-1'], ['tag-2']), }); - context.core.elasticsearch.client.asCurrentUser.updateByQuery.mockResponse( - getSuccessfulSignalUpdateResponse() - ); - - const response = await server.inject(request, requestContextMock.convertContext(context)); - - context.core.elasticsearch.client.asCurrentUser.updateByQuery.mockRejectedValue( - new Error('Test error') - ); + const result = server.validate(request); - expect(response.body).toEqual({ - message: [`No alert ids were provided`], - status_code: 400, - }); + expect(result.badRequest).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts index 8b7e81f9bf812..95d722ac0a381 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts @@ -7,15 +7,14 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { uniq } from 'lodash/fp'; -import type { SetAlertTagsRequestBodyDecoded } from '../../../../../common/api/detection_engine/alert_tags'; -import { setAlertTagsRequestBody } from '../../../../../common/api/detection_engine/alert_tags'; +import { ManageAlertTagsRequestBody } from '../../../../../common/api/detection_engine/alert_tags'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DEFAULT_ALERTS_INDEX, DETECTION_ENGINE_ALERT_TAGS_URL, } from '../../../../../common/constants'; import { buildSiemResponse } from '../utils'; -import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { validateAlertTagsArrays } from './helpers'; export const setAlertTagsRoute = (router: SecuritySolutionPluginRouter) => { @@ -32,10 +31,7 @@ export const setAlertTagsRoute = (router: SecuritySolutionPluginRouter) => { version: '2023-10-31', validate: { request: { - body: buildRouteValidation< - typeof setAlertTagsRequestBody, - SetAlertTagsRequestBodyDecoded - >(setAlertTagsRequestBody), + body: buildRouteValidationWithZod(ManageAlertTagsRequestBody), }, }, }, diff --git a/x-pack/test/api_integration/services/security_solution_api.gen.ts b/x-pack/test/api_integration/services/security_solution_api.gen.ts index 7650153c53ca3..4bc611e50bba2 100644 --- a/x-pack/test/api_integration/services/security_solution_api.gen.ts +++ b/x-pack/test/api_integration/services/security_solution_api.gen.ts @@ -19,18 +19,22 @@ import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; +import { AlertsMigrationCleanupRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/delete_signals_migration/delete_signals_migration.gen'; import { BulkCreateRulesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_create_rules/bulk_create_rules_route.gen'; import { BulkDeleteRulesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_delete_rules/bulk_delete_rules_route.gen'; import { BulkPatchRulesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_patch_rules/bulk_patch_rules_route.gen'; import { BulkUpdateRulesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_update_rules/bulk_update_rules_route.gen'; +import { CreateAlertsMigrationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.gen'; import { CreateRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/create_rule/create_rule_route.gen'; import { DeleteRuleRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/delete_rule/delete_rule_route.gen'; import { ExportRulesRequestQueryInput, ExportRulesRequestBodyInput, } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/export_rules/export_rules_route.gen'; +import { FinalizeAlertsMigrationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen'; import { FindRulesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/find_rules/find_rules_route.gen'; import { GetAgentPolicySummaryRequestQueryInput } from '@kbn/security-solution-plugin/common/api/endpoint/policy/policy.gen'; +import { GetAlertsMigrationStatusRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.gen'; import { GetEndpointSuggestionsRequestParamsInput, GetEndpointSuggestionsRequestBodyInput, @@ -45,13 +49,16 @@ import { GetRuleExecutionResultsRequestParamsInput, } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.gen'; import { ImportRulesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/import_rules/import_rules_route.gen'; +import { ManageAlertTagsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.gen'; import { PatchRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.gen'; import { PerformBulkActionRequestQueryInput, PerformBulkActionRequestBodyInput, } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.gen'; import { ReadRuleRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.gen'; +import { SearchAlertsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals/query_signals/query_signals_route.gen'; import { SetAlertAssigneesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/alert_assignees/set_alert_assignees_route.gen'; +import { SetAlertsStatusRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen'; import { SuggestUserProfilesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/users/suggest_user_profiles_route.gen'; import { UpdateRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/update_rule/update_rule_route.gen'; import { FtrProviderContext } from '../ftr_provider_context'; @@ -60,6 +67,22 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) const supertest = getService('supertest'); return { + /** + * Migrations favor data integrity over shard size. Consequently, unused or orphaned indices are artifacts of +the migration process. A successful migration will result in both the old and new indices being present. +As such, the old, orphaned index can (and likely should) be deleted. While you can delete these indices manually, +the endpoint accomplishes this task by applying a deletion policy to the relevant index, causing it to be deleted +after 30 days. It also deletes other artifacts specific to the migration implementation. + + */ + alertsMigrationCleanup(props: AlertsMigrationCleanupProps) { + return supertest + .delete('/api/detection_engine/signals/migration') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(props.body as object); + }, /** * Creates new detection rules in bulk. */ @@ -104,6 +127,14 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(props.body as object); }, + createAlertsMigration(props: CreateAlertsMigrationProps) { + return supertest + .post('/api/detection_engine/signals/migration') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(props.body as object); + }, /** * Create a single detection rule */ @@ -138,6 +169,20 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) .send(props.body as object) .query(props.query); }, + /** + * The finalization endpoint replaces the original index's alias with the successfully migrated index's alias. +The endpoint is idempotent; therefore, it can safely be used to poll a given migration and, upon completion, +finalize it. + + */ + finalizeAlertsMigration(props: FinalizeAlertsMigrationProps) { + return supertest + .post('/api/detection_engine/signals/finalize_migration') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(props.body as object); + }, /** * Finds rules that match the given query. */ @@ -157,6 +202,14 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .query(props.query); }, + getAlertsMigrationStatus(props: GetAlertsMigrationStatusProps) { + return supertest + .post('/api/detection_engine/signals/migration_status') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .query(props.query); + }, getEndpointSuggestions(props: GetEndpointSuggestionsProps) { return supertest .post(replaceParams('/api/endpoint/suggestions/{suggestion_type}', props.params)) @@ -218,6 +271,14 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); }, + manageAlertTags(props: ManageAlertTagsProps) { + return supertest + .post('/api/detection_engine/signals/tags') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(props.body as object); + }, /** * Patch a single rule */ @@ -259,6 +320,14 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); }, + searchAlerts(props: SearchAlertsProps) { + return supertest + .post('/api/detection_engine/signals/search') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(props.body as object); + }, /** * Assigns users to alerts. */ @@ -270,6 +339,14 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(props.body as object); }, + setAlertsStatus(props: SetAlertsStatusProps) { + return supertest + .post('/api/detection_engine/signals/status') + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(props.body as object); + }, /** * Suggests user profiles. */ @@ -295,6 +372,9 @@ export function SecuritySolutionApiProvider({ getService }: FtrProviderContext) }; } +export interface AlertsMigrationCleanupProps { + body: AlertsMigrationCleanupRequestBodyInput; +} export interface BulkCreateRulesProps { body: BulkCreateRulesRequestBodyInput; } @@ -307,6 +387,9 @@ export interface BulkPatchRulesProps { export interface BulkUpdateRulesProps { body: BulkUpdateRulesRequestBodyInput; } +export interface CreateAlertsMigrationProps { + body: CreateAlertsMigrationRequestBodyInput; +} export interface CreateRuleProps { body: CreateRuleRequestBodyInput; } @@ -317,12 +400,18 @@ export interface ExportRulesProps { query: ExportRulesRequestQueryInput; body: ExportRulesRequestBodyInput; } +export interface FinalizeAlertsMigrationProps { + body: FinalizeAlertsMigrationRequestBodyInput; +} export interface FindRulesProps { query: FindRulesRequestQueryInput; } export interface GetAgentPolicySummaryProps { query: GetAgentPolicySummaryRequestQueryInput; } +export interface GetAlertsMigrationStatusProps { + query: GetAlertsMigrationStatusRequestQueryInput; +} export interface GetEndpointSuggestionsProps { params: GetEndpointSuggestionsRequestParamsInput; body: GetEndpointSuggestionsRequestBodyInput; @@ -341,6 +430,9 @@ export interface GetRuleExecutionResultsProps { export interface ImportRulesProps { query: ImportRulesRequestQueryInput; } +export interface ManageAlertTagsProps { + body: ManageAlertTagsRequestBodyInput; +} export interface PatchRuleProps { body: PatchRuleRequestBodyInput; } @@ -351,9 +443,15 @@ export interface PerformBulkActionProps { export interface ReadRuleProps { query: ReadRuleRequestQueryInput; } +export interface SearchAlertsProps { + body: SearchAlertsRequestBodyInput; +} export interface SetAlertAssigneesProps { body: SetAlertAssigneesRequestBodyInput; } +export interface SetAlertsStatusProps { + body: SetAlertsStatusRequestBodyInput; +} export interface SuggestUserProfilesProps { query: SuggestUserProfilesRequestQueryInput; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/ess_specific_index_logic/migrations/create_alerts_migrations.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/ess_specific_index_logic/migrations/create_alerts_migrations.ts index 389527a532b40..12058ababe0dc 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/ess_specific_index_logic/migrations/create_alerts_migrations.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/ess_specific_index_logic/migrations/create_alerts_migrations.ts @@ -70,11 +70,14 @@ export default ({ getService }: FtrProviderContext): void => { // Finalize the migration after each test so that the .siem-signals alias gets added to the migrated index - // this allows deleteSignalsIndex to find and delete the migrated index await sleep(5000); // Allow the migration to complete - await supertest - .post(DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL) - .set('kbn-xsrf', 'true') - .send({ migration_ids: createdMigrations.map((m) => m.migration_id) }) - .expect(200); + + if (createdMigrations.length > 0) { + await supertest + .post(DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL) + .set('kbn-xsrf', 'true') + .send({ migration_ids: createdMigrations.map((m) => m.migration_id) }) + .expect(200); + } await esArchiver.unload('x-pack/test/functional/es_archives/signals/outdated_signals_index'); await esArchiver.unload('x-pack/test/functional/es_archives/signals/legacy_signals_index'); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/field_aliases.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/field_aliases.ts index b6c6d265c14da..732bb54385a8a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/field_aliases.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/field_aliases.ts @@ -39,12 +39,9 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createAlertsIndex(supertest, log); - }); - - afterEach(async () => { await deleteAllAlerts(supertest, log, es); await deleteAllRules(supertest, log); + await createAlertsIndex(supertest, log); }); it('should keep the original alias value such as "host_alias" from a source index when the value is indexed', async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/query_alerts.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/query_alerts.ts index 95764a6894fd4..63875d58f5d90 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/query_alerts.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/query_alerts.ts @@ -35,6 +35,10 @@ export default ({ getService }: FtrProviderContext) => { const es = getService('es'); describe('@ess @serverless @serverlessQA query_signals_route and find_alerts_route', () => { + beforeEach(async () => { + await deleteAllAlerts(supertest, log, es); + }); + describe('validation checks', () => { it('should not give errors when querying and the alerts index does exist and is empty', async () => { await createAlertsIndex(supertest, log); @@ -61,7 +65,7 @@ export default ({ getService }: FtrProviderContext) => { }); describe('runtime fields', () => { - before(async () => { + beforeEach(async () => { await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/alerts/8.8.0_multiple_docs', { @@ -71,7 +75,7 @@ export default ({ getService }: FtrProviderContext) => { ); await createAlertsIndex(supertest, log); }); - after(async () => { + afterEach(async () => { await deleteAllAlerts(supertest, log, es); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/set_alert_tags.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/set_alert_tags.ts index e0b09a111ae0c..961150d0908c2 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/set_alert_tags.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/set_alert_tags.ts @@ -5,7 +5,7 @@ * 2.0. */ -import expect from '@kbn/expect'; +import expect from 'expect'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { @@ -49,9 +49,10 @@ export default ({ getService }: FtrProviderContext) => { .send(setAlertTags({ tagsToAdd: [], tagsToRemove: [], ids: [] })) .expect(400); - expect(body).to.eql({ - message: ['No alert ids were provided'], - status_code: 400, + expect(body).toEqual({ + error: 'Bad Request', + message: '[request body]: ids: Array must contain at least 1 element(s)', + statusCode: 400, }); }); @@ -62,7 +63,7 @@ export default ({ getService }: FtrProviderContext) => { .send(setAlertTags({ tagsToAdd: ['test-1'], tagsToRemove: ['test-1'], ids: ['123'] })) .expect(400); - expect(body).to.eql({ + expect(body).toEqual({ message: [ 'Duplicate tags ["test-1"] were found in the tags_to_add and tags_to_remove parameters.', ], @@ -119,7 +120,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); body.hits.hits.map((alert) => { - expect(alert._source?.['kibana.alert.workflow_tags']).to.eql(['tag-1']); + expect(alert._source?.['kibana.alert.workflow_tags']).toEqual(['tag-1']); }); }); @@ -165,7 +166,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); body.hits.hits.map((alert) => { - expect(alert._source?.['kibana.alert.workflow_tags']).to.eql(['tag-1']); + expect(alert._source?.['kibana.alert.workflow_tags']).toEqual(['tag-1']); }); }); @@ -211,7 +212,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); body.hits.hits.map((alert) => { - expect(alert._source?.['kibana.alert.workflow_tags']).to.eql(['tag-1']); + expect(alert._source?.['kibana.alert.workflow_tags']).toEqual(['tag-1']); }); }); @@ -245,7 +246,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); body.hits.hits.map((alert) => { - expect(alert._source?.['kibana.alert.workflow_tags']).to.eql([]); + expect(alert._source?.['kibana.alert.workflow_tags']).toEqual([]); }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/set_alert_tags.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/set_alert_tags.ts index b3ae1d4de0b5c..f826629741179 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/set_alert_tags.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/set_alert_tags.ts @@ -6,7 +6,7 @@ */ import { AlertTagIds } from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { SetAlertTagsRequestBody } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { ManageAlertTagsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine'; export const setAlertTags = ({ tagsToAdd, @@ -16,7 +16,7 @@ export const setAlertTags = ({ tagsToAdd: string[]; tagsToRemove: string[]; ids: AlertTagIds; -}): SetAlertTagsRequestBody => ({ +}): ManageAlertTagsRequestBodyInput => ({ tags: { tags_to_add: tagsToAdd, tags_to_remove: tagsToRemove, From cc7dee61d2f8927f0c6c24d5754cf8c639b4c86d Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 18 Jun 2024 11:55:00 -0400 Subject: [PATCH 061/127] [Synthetics] Fix TLS cert view for > 3 monitors per cert (#186204) ## Summary Resolves #183985. This patch makes it so we can see more than three monitors per cert in the TLS page of Synthetics. I've set the default limit to the round number of 100. Realistically, users could have more than 100 monitors for the same cert, but also realistically, this page would need a layout overhaul to display that many monitors in a single row as well. ### Before image ### After image ## Testing this PR Follow the simple repro instructions in the linked issue. On `main`, you should only see 3 or less monitors. On this branch, you should see all monitors. --- .../synthetics/common/requests/get_certs_request_body.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/observability_solution/synthetics/common/requests/get_certs_request_body.ts b/x-pack/plugins/observability_solution/synthetics/common/requests/get_certs_request_body.ts index f4535f2f85b72..fa1bd9eafad32 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/requests/get_certs_request_body.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/requests/get_certs_request_body.ts @@ -151,6 +151,7 @@ export const getCertsRequestBody = ({ collapse: { field: 'tls.server.hash.sha256', inner_hits: { + size: 100, _source: { includes: ['monitor.id', 'monitor.name', 'url.full', 'config_id'], }, From 946a255bc5450c577546237bf450a99637632427 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 18 Jun 2024 17:55:26 +0200 Subject: [PATCH 062/127] Upgrade EUI to v95.0.0 (#185943) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `v94.6.0` ⏩ `v95.0.0-backport.0` _[Questions? Please see our Kibana upgrade FAQ.](https://github.com/elastic/eui/blob/main/wiki/eui-team-processes/upgrading-kibana.md#faq-for-kibana-teams)_ --- ## [`v95.0.0-backport.0`](https://github.com/elastic/eui/releases/v95.0.0-backport.0) **This is a backport release only intended for use by Kibana.** - Updated `EuiSteps` to support a new `titleSize="xxs"` style, which outputs the same title font size but smaller unnumbered step indicators ([#7813](https://github.com/elastic/eui/pull/7813)) - Updated `EuiStepsHorizontal` to support a new `size="xs"` style, which outputs smaller unnumbered step indicators ([#7813](https://github.com/elastic/eui/pull/7813)) - Updated `EuiStepNumber` to support new `titleSize="none"` which omits rendering step numbers, and will only render icons ([#7813](https://github.com/elastic/eui/pull/7813)) ## [`v95.0.0`](https://github.com/elastic/eui/releases/v95.0.0) - Added `move` glyph to `EuiIcon` ([#7789](https://github.com/elastic/eui/pull/7789)) - Updated `EuiBasicTable` and `EuiInMemoryTable`s with `selection` - the header row checkbox will now render an indeterminate state if some (but not all) rows are selected ([#7817](https://github.com/elastic/eui/pull/7817)) **Bug fixes** - Fixed an `EuiDataGrid` visual bug when using `lineCount` row heights where the clamped text was still visible for some font sizes ([#7793](https://github.com/elastic/eui/pull/7793)) - Fixed `EuiSearchBar`'s filter configs to always respect `autoClose: false` ([#7806](https://github.com/elastic/eui/pull/7806)) **Breaking changes** - Removed deprecated `EUI_CHARTS_THEME_DARK`, `EUI_CHARTS_THEME_LIGHT` and `EUI_SPARKLINE_THEME_PARTIAL` exports ([#7682](https://github.com/elastic/eui/pull/7682)) - Removed deprecated `euiPalettePositive` and `euiPaletteNegative`. Use `euiPaletteGreen` and `euiPaletteRed` instead ([#7808](https://github.com/elastic/eui/pull/7808)) - Removed `type="inList"` from `EuiCheckbox`. Simply omit passing a `label` prop to render this style of checkbox ([#7814](https://github.com/elastic/eui/pull/7814)) - Removed the unused `compressed` prop from `EuiCheckbox` and `EuiRadio`. This prop was not doing anything on individual components. ([#7818](https://github.com/elastic/eui/pull/7818)) **CSS-in-JS conversions** - Converted `EuiCheckboxGroup` to Emotion ([#7818](https://github.com/elastic/eui/pull/7818)) - Converted `EuiRadioGroup` to Emotion ([#7818](https://github.com/elastic/eui/pull/7818)) --------- Co-authored-by: Cee Chen Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com> --- .../app/pages/page_reducer_stream/index.tsx | 3 --- .../app/pages/page_redux_stream/index.tsx | 3 --- .../pages/page_simple_string_stream/index.tsx | 1 - package.json | 2 +- .../__snapshots__/i18n_service.test.tsx.snap | 1 + .../src/i18n_eui_mapping.tsx | 3 +++ .../kbn-ui-shared-deps-npm/webpack.config.js | 1 - .../kbn-ui-shared-deps-src/src/definitions.js | 1 - packages/kbn-ui-shared-deps-src/src/entry.js | 1 - src/dev/license_checker/config.ts | 2 +- .../component/control_group_component.tsx | 1 - .../system_prompt_settings.tsx | 1 - .../views/multi_checkbox_facets_view.tsx | 1 - .../cypress/e2e/fleet_settings_outputs.cy.ts | 20 ++++++++++--------- .../fleet/cypress/screens/fleet_outputs.ts | 8 ++++---- .../output_form_kafka_partitioning.tsx | 2 +- .../screens/detail/settings/update_button.tsx | 1 - .../actions_section.test.js.snap | 18 ----------------- .../rule_editor_flyout.test.js.snap | 6 ------ .../scope_expression.test.js.snap | 12 ----------- .../__snapshots__/scope_section.test.js.snap | 15 -------------- .../imported_events.test.js.snap | 3 --- .../waterfall/waterfall_filter.tsx | 1 - .../kibana/feature_table/sub_feature_form.tsx | 1 - .../expression/es_query_expression.tsx | 4 +++- .../functional/tests/feature_control.ts | 3 +-- yarn.lock | 8 ++++---- 27 files changed, 30 insertions(+), 93 deletions(-) diff --git a/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx b/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx index a471d6f589034..4bded9ac1e27f 100644 --- a/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx +++ b/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx @@ -132,21 +132,18 @@ export const PageReducerStream: FC = () => { label="Simulate errors (gets applied to new streams only, not currently running ones)." checked={simulateErrors} onChange={(e) => setSimulateErrors(!simulateErrors)} - compressed /> setCompressResponse(!compressResponse)} - compressed /> setFlushFix(!flushFix)} - compressed /> diff --git a/examples/response_stream/public/containers/app/pages/page_redux_stream/index.tsx b/examples/response_stream/public/containers/app/pages/page_redux_stream/index.tsx index aaf0a7b5dbbb7..15512ac92d12d 100644 --- a/examples/response_stream/public/containers/app/pages/page_redux_stream/index.tsx +++ b/examples/response_stream/public/containers/app/pages/page_redux_stream/index.tsx @@ -136,21 +136,18 @@ export const PageReduxStream: FC = () => { label="Simulate errors (gets applied to new streams only, not currently running ones)." checked={simulateErrors} onChange={(e) => dispatch(setSimulateErrors(!simulateErrors))} - compressed /> dispatch(setCompressResponse(!compressResponse))} - compressed /> dispatch(setFlushFix(!flushFix))} - compressed /> diff --git a/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx b/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx index 3e33ade381489..981329dfcec3a 100644 --- a/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx +++ b/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx @@ -83,7 +83,6 @@ export const PageSimpleStringStream: FC = () => { label="Toggle compression setting for response stream." checked={compressResponse} onChange={(e) => setCompressResponse(!compressResponse)} - compressed /> diff --git a/package.json b/package.json index d893459351783..0c50f51a82f2e 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@elastic/ecs": "^8.11.1", "@elastic/elasticsearch": "^8.13.1", "@elastic/ems-client": "8.5.1", - "@elastic/eui": "94.6.0", + "@elastic/eui": "95.0.0-backport.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", diff --git a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap index fd8ba14e035cf..67fe5f2a46221 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap +++ b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap @@ -12,6 +12,7 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiAutoRefresh.autoRefreshLabel": "Auto refresh", "euiAutoRefresh.buttonLabelOff": "Auto refresh is off", "euiAutoRefresh.buttonLabelOn": [Function], + "euiBasicTable.deselectRows": "Deselect rows", "euiBasicTable.noItemsMessage": "No items found", "euiBasicTable.selectAllRows": "Select all rows", "euiBasicTable.selectThisRow": [Function], diff --git a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx index 4d6fcf64ab081..151a94bd3ce22 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx +++ b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx @@ -85,6 +85,9 @@ export const getEuiContextMapping = (): EuiTokensObject => { 'euiBasicTable.noItemsMessage': i18n.translate('core.euiBasicTable.noItemsMessage', { defaultMessage: 'No items found', }), + 'euiBasicTable.deselectRows': i18n.translate('core.euiBasicTable.deselectRows', { + defaultMessage: 'Deselect rows', + }), 'euiBottomBar.customScreenReaderAnnouncement': ({ landmarkHeading }: EuiValues) => i18n.translate('core.euiBottomBar.customScreenReaderAnnouncement', { defaultMessage: diff --git a/packages/kbn-ui-shared-deps-npm/webpack.config.js b/packages/kbn-ui-shared-deps-npm/webpack.config.js index 79502207aea00..24085109d0d56 100644 --- a/packages/kbn-ui-shared-deps-npm/webpack.config.js +++ b/packages/kbn-ui-shared-deps-npm/webpack.config.js @@ -63,7 +63,6 @@ module.exports = (_, argv) => { '@elastic/eui/optimize/es/components/provider/nested', '@elastic/eui/optimize/es/services', '@elastic/eui/optimize/es/services/format', - '@elastic/eui/dist/eui_charts_theme', '@elastic/eui/dist/eui_theme_light.json', '@elastic/eui/dist/eui_theme_dark.json', '@elastic/numeral', diff --git a/packages/kbn-ui-shared-deps-src/src/definitions.js b/packages/kbn-ui-shared-deps-src/src/definitions.js index 78ee1229da4e9..b2b38e131fb80 100644 --- a/packages/kbn-ui-shared-deps-src/src/definitions.js +++ b/packages/kbn-ui-shared-deps-src/src/definitions.js @@ -75,7 +75,6 @@ const externals = { '__kbnSharedDeps__.ElasticEuiLibComponentsUseIsNestedEuiProvider', '@elastic/eui/lib/services': '__kbnSharedDeps__.ElasticEuiLibServices', '@elastic/eui/lib/services/format': '__kbnSharedDeps__.ElasticEuiLibServicesFormat', - '@elastic/eui/dist/eui_charts_theme': '__kbnSharedDeps__.ElasticEuiChartsTheme', // transient dep of eui '@hello-pangea/dnd': '__kbnSharedDeps__.HelloPangeaDnd', diff --git a/packages/kbn-ui-shared-deps-src/src/entry.js b/packages/kbn-ui-shared-deps-src/src/entry.js index b012cb5660113..1d0e88ef0efd8 100644 --- a/packages/kbn-ui-shared-deps-src/src/entry.js +++ b/packages/kbn-ui-shared-deps-src/src/entry.js @@ -42,7 +42,6 @@ export const ElasticEui = require('@elastic/eui'); export const ElasticEuiLibComponentsUseIsNestedEuiProvider = require('@elastic/eui/optimize/es/components/provider/nested'); export const ElasticEuiLibServices = require('@elastic/eui/optimize/es/services'); export const ElasticEuiLibServicesFormat = require('@elastic/eui/optimize/es/services/format'); -export const ElasticEuiChartsTheme = require('@elastic/eui/dist/eui_charts_theme'); export const KbnDatemath = require('@kbn/datemath'); export const HelloPangeaDnd = require('@hello-pangea/dnd/dist/dnd'); export const ReduxjsToolkit = require('@reduxjs/toolkit'); diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index b7642cf7e9af7..45262fd3a57cc 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -86,7 +86,7 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.5.1': ['Elastic License 2.0'], - '@elastic/eui@94.6.0': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@95.0.0-backport.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry 'buffers@0.1.1': ['MIT'], // license in importing module https://www.npmjs.com/package/binary '@bufbuild/protobuf@1.2.1': ['Apache-2.0'], // license (Apache-2.0 AND BSD-3-Clause) diff --git a/src/plugins/controls/public/control_group/component/control_group_component.tsx b/src/plugins/controls/public/control_group/component/control_group_component.tsx index 56a50e596870c..019ef9256e91b 100644 --- a/src/plugins/controls/public/control_group/component/control_group_component.tsx +++ b/src/plugins/controls/public/control_group/component/control_group_component.tsx @@ -168,7 +168,6 @@ export const ControlGroup = () => { content={ControlGroupStrings.invalidControlWarning.getTourContent(invalidControlType)} footerAction={[ = React.memo( } checked={isNewConversationDefault} onChange={handleNewConversationDefaultChange} - compressed /> diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx index 4ddd0920038e1..19727db552acf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx @@ -84,7 +84,6 @@ export const MultiCheckboxFacetsView: React.FC = ({ options={checkboxGroupOptions} idToSelectedMap={idToSelectedMap} onChange={onChange} - compressed /> {showMore && ( <> diff --git a/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts b/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts index 965dcf48eed6e..4fc4fa33ea5b0 100644 --- a/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts @@ -281,7 +281,7 @@ queue: }); // Verify SSL fields - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_SSL_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_SSL_OPTION).find('label').click(); cy.get('[placeholder="Specify certificate authority"]'); cy.get('[placeholder="Specify ssl certificate"]'); cy.get('[placeholder="Specify certificate key"]'); @@ -292,7 +292,7 @@ queue: // Verify None fields - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_NONE_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_NONE_OPTION).find('label').click(); cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_SASL_SELECT).should('not.exist'); cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_INPUT).should('not.exist'); @@ -308,14 +308,16 @@ queue: cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_CONNECTION_TYPE_PLAIN_OPTION); cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_CONNECTION_TYPE_ENCRYPTION_OPTION); - cy.getBySel( - SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_CONNECTION_TYPE_ENCRYPTION_OPTION - ).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_CONNECTION_TYPE_ENCRYPTION_OPTION) + .find('label') + .click(); cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_VERIFICATION_MODE_INPUT); cy.get('[placeholder="Specify certificate authority"]'); - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_PASSWORD_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_PASSWORD_OPTION) + .find('label') + .click(); // Verify Partitioning fields cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_PANEL).within(() => { @@ -327,13 +329,13 @@ queue: }); // Verify Round Robin fields - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_RANDOM_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_RANDOM_OPTION).find('label').click(); cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_EVENTS_INPUT); // Verify Hash fields - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_HASH_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_HASH_OPTION).find('label').click(); cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_HASH_INPUT); - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_RANDOM_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_RANDOM_OPTION).find('label').click(); // Topics cy.getBySel(SETTINGS_OUTPUTS_KAFKA.TOPICS_PANEL).within(() => { diff --git a/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts b/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts index eb4d3310e113d..763e6fae1b1ef 100644 --- a/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts +++ b/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts @@ -31,7 +31,7 @@ export const selectKafkaOutput = () => { visit('/app/fleet/settings'); cy.getBySel(SETTINGS_OUTPUTS.ADD_BTN).click(); cy.getBySel(SETTINGS_OUTPUTS.TYPE_INPUT).select('kafka'); - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_PASSWORD_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_PASSWORD_OPTION).find('label').click(); }; export const shouldDisplayError = (handler: string) => { @@ -190,8 +190,8 @@ export const fillInKafkaOutputForm = (create?: boolean) => { ); cy.get('[placeholder="Specify certificate authority"]').clear().type('testCA'); - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_SASL_SCRAM_256_OPTION).click(); - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_HASH_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_SASL_SCRAM_256_OPTION).find('label').click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.PARTITIONING_HASH_OPTION).find('label').click(); cy.getBySel(kafkaOutputFormValues.hash.selector).type(kafkaOutputFormValues.hash.value); cy.getBySel(kafkaOutputFormValues.defaultTopic.selector).type( @@ -265,7 +265,7 @@ export const validateOutputTypeChangeToKafka = (outputId: string) => { visit(`/app/fleet/settings/outputs/${outputId}`); cy.getBySel(kafkaOutputFormValues.name.selector).clear(); cy.getBySel(SETTINGS_OUTPUTS.TYPE_INPUT).select('kafka'); - cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_PASSWORD_OPTION).click(); + cy.getBySel(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_PASSWORD_OPTION).find('label').click(); fillInKafkaOutputForm(true); cy.intercept('PUT', '**/api/fleet/outputs/**').as('saveOutput'); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx index 6acb44fe33af5..d5f7de712cd86 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx @@ -140,7 +140,7 @@ export const OutputFormKafkaPartitioning: React.FunctionComponent<{ } > = ({ {packagePolicyCount > 0 && ( @@ -393,10 +391,8 @@ exports[`RuleEditorFlyout renders the flyout after setting the rule to edit 1`] @@ -629,10 +625,8 @@ exports[`RuleEditorFlyout renders the flyout for creating a rule with conditions diff --git a/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_expression.test.js.snap b/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_expression.test.js.snap index 4347958d240c0..f5b266b67062c 100644 --- a/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_expression.test.js.snap +++ b/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_expression.test.js.snap @@ -10,10 +10,7 @@ exports[`ScopeExpression renders when empty list of filter IDs is supplied 1`] = > @@ -46,10 +43,7 @@ exports[`ScopeExpression renders when enabled set to false 1`] = ` > @@ -190,10 +184,7 @@ exports[`ScopeExpression renders when filter ID and type supplied 1`] = ` > @@ -334,10 +325,7 @@ exports[`ScopeExpression renders when no filter ID or type supplied 1`] = ` > diff --git a/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_section.test.js.snap b/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_section.test.js.snap index c61f9a3d30d7d..110530cd03e97 100644 --- a/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_section.test.js.snap +++ b/x-pack/plugins/ml/public/application/components/rule_editor/__snapshots__/scope_section.test.js.snap @@ -17,10 +17,7 @@ exports[`ScopeSection false canGetFilters privilege show NoPermissionCallOut whe /> 0)} id="onlyHighlighted" label={FILTER_COLLAPSE_REQUESTS_LABEL} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx index 03ed9597fcb2d..4f3c1eb103a75 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx @@ -130,7 +130,6 @@ export const SubFeatureForm = (props: Props) => { }} checked={isGranted} disabled={props.disabled} - compressed={true} /> ); })} diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx index 0c749b175b2e6..fd68e61ecb987 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx @@ -345,7 +345,9 @@ export const EsQueryExpression: React.FC< errors={errors} hasValidationErrors={hasExpressionValidationErrors(currentRuleParams, isServerless)} onTestFetch={onTestQuery} - excludeHitsFromPreviousRun={excludeHitsFromPreviousRun} + excludeHitsFromPreviousRun={ + excludeHitsFromPreviousRun ?? DEFAULT_VALUES.EXCLUDE_PREVIOUS_HITS + } onChangeExcludeHitsFromPreviousRun={useCallback( (exclude) => setParam('excludeHitsFromPreviousRun', exclude), [setParam] diff --git a/x-pack/test/saved_object_tagging/functional/tests/feature_control.ts b/x-pack/test/saved_object_tagging/functional/tests/feature_control.ts index f226423100451..463c2f5be82f4 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/feature_control.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/feature_control.ts @@ -45,8 +45,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const unselectTags = async () => { if (await tagManagementPage.isSelectionColumnDisplayed()) { - await tagManagementPage.selectAllTagRows(); - await tagManagementPage.selectAllTagRows(); + await tagManagementPage.clickOnBulkAction('clear_selection'); } }; diff --git a/yarn.lock b/yarn.lock index 834ac4b058356..07416bc65a2e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1720,10 +1720,10 @@ resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314" integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ== -"@elastic/eui@94.6.0": - version "94.6.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-94.6.0.tgz#fd56be1dbdcdea259cdb3504085c8479fa35bcef" - integrity sha512-lYXVcylXn4Iz2WumBuOEkc1PRFoUby7CTnNhTS/gVrbTP7Mn0ombcoPFUSiZcA7VuN2mHfPmTUdBQptC/apTzA== +"@elastic/eui@95.0.0-backport.0": + version "95.0.0-backport.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-95.0.0-backport.0.tgz#6fdfbc813259cf82896f24641bb6e8a03587f3e8" + integrity sha512-aaCQYLdJ4/1uQUb8xsToa94HwUDN2HSjtZzrgh3iT3El7tieNk6TNzX9QtNePw9M57snpdt41wyg6QFM7Jhltg== dependencies: "@hello-pangea/dnd" "^16.6.0" "@types/lodash" "^4.14.202" From 641a71bb68259d2650e5071c6f333f661c3b8e2e Mon Sep 17 00:00:00 2001 From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com> Date: Tue, 18 Jun 2024 18:30:40 +0200 Subject: [PATCH 063/127] Improve logic for dashboard duplication title computation (#185056) ## Summary follow up to https://github.com/elastic/kibana/pull/184777#discussion_r1631353032 Previously, if a user has cloned a dashboard N times, in the worst case that the next duplication attempt is initiated from the initial dashboard N network calls would be required to find a unique title for the next uniquely titled clone. This update short circuits that process by querying for the last created dashboard, getting it's duplicationId, increment it and proposing it as the next dashboard duplicate title, with this approach there's still a chance we might suggest a dashboard title that's been claimed if the user modifies the dashboard title to a higher duplication Id after creation, especially that we are querying for the last created and this is situation we can't correct for, the resolution for the appropriate title in that case would be on the user. ## How to test - Create couple of duplicated dashboards, the titles should follow the normal increment progression ie. n+1 - Create some that skip the expected pattern by any increment of choice, on attempting to duplicate this dashboard the suggested title should be previous + 1 - Choose to duplicate any previously created dashboard the suggested title should be the increment of the last duplicated dashboard ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Catherine Liu --- .../embeddable/api/run_save_functions.tsx | 27 ++-- ...heck_for_duplicate_dashboard_title.test.ts | 120 ++++++++++++++++++ .../check_for_duplicate_dashboard_title.ts | 37 +++++- .../apps/dashboard/group4/dashboard_clone.ts | 15 +++ 4 files changed, 178 insertions(+), 21 deletions(-) create mode 100644 src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.test.ts diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/api/run_save_functions.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/api/run_save_functions.tsx index 049bfaf00e5dd..67cad4bd7bf83 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/api/run_save_functions.tsx +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/api/run_save_functions.tsx @@ -275,21 +275,18 @@ export async function runInteractiveSave(this: DashboardContainer, interactionMo if (lastSavedId) { const [baseTitle, baseCount] = extractTitleAndCount(newTitle); - let copyCount = baseCount + 1; - newTitle = `${baseTitle} (${copyCount})`; - - // increment count until we find a unique title - while ( - !(await checkForDuplicateDashboardTitle({ - title: newTitle, - lastSavedTitle: currentState.title, - copyOnSave: true, - isTitleDuplicateConfirmed: false, - })) - ) { - copyCount++; - newTitle = `${baseTitle} (${copyCount})`; - } + + newTitle = `${baseTitle} (${baseCount + 1})`; + + await checkForDuplicateDashboardTitle({ + title: newTitle, + lastSavedTitle: currentState.title, + copyOnSave: true, + isTitleDuplicateConfirmed: false, + onTitleDuplicate(speculativeSuggestion) { + newTitle = speculativeSuggestion; + }, + }); switch (interactionMode) { case ViewMode.EDIT: { diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.test.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.test.ts new file mode 100644 index 0000000000000..edaae6a8b0d92 --- /dev/null +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright 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 { ContentClient } from '@kbn/content-management-plugin/public'; +import { checkForDuplicateDashboardTitle } from './check_for_duplicate_dashboard_title'; +import { extractTitleAndCount } from '../../../dashboard_container/embeddable/api/lib/extract_title_and_count'; + +type ContentManagementStart = Parameters[1]; + +describe('checkForDuplicateDashboardTitle', () => { + const mockedContentManagementClient = { + search: jest.fn(), + } as unknown as ContentClient; + + const newTitle = 'Shiny dashboard (1)'; + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('will only search using the dashboard basename', async () => { + const [baseDashboardName] = extractTitleAndCount(newTitle); + + const pageResults = [ + { + attributes: { + title: baseDashboardName, + }, + }, + ]; + + ( + mockedContentManagementClient.search as jest.MockedFunction + ).mockImplementationOnce(() => + Promise.resolve({ + hits: pageResults, + pagination: { + total: pageResults.length, + }, + }) + ); + + await checkForDuplicateDashboardTitle( + { + title: newTitle, + lastSavedTitle: baseDashboardName, + copyOnSave: true, + isTitleDuplicateConfirmed: false, + }, + { client: mockedContentManagementClient } as ContentManagementStart + ); + + expect(mockedContentManagementClient.search).toHaveBeenCalledWith( + expect.objectContaining({ + query: expect.objectContaining({ + text: `${baseDashboardName}*`, + }), + }) + ); + }); + + it('invokes onTitleDuplicate with a speculative collision free value when the new title provided is a duplicate match', async () => { + const [baseDashboardName] = extractTitleAndCount(newTitle); + + const userTitleInput = `${baseDashboardName} (10)`; + + const pageResults = [ + { + attributes: { + title: baseDashboardName, + }, + }, + ].concat( + Array.from(new Array(5)).map((_, idx) => ({ + attributes: { + title: `${baseDashboardName} (${10 + idx})`, + }, + })) + ); + + const onTitleDuplicate = jest.fn(); + + ( + mockedContentManagementClient.search as jest.MockedFunction + ).mockImplementationOnce(() => + Promise.resolve({ + hits: pageResults, + pagination: { + total: pageResults.length, + }, + }) + ); + + await checkForDuplicateDashboardTitle( + { + title: userTitleInput, + lastSavedTitle: baseDashboardName, + copyOnSave: true, + isTitleDuplicateConfirmed: false, + onTitleDuplicate, + }, + { client: mockedContentManagementClient } as ContentManagementStart + ); + + expect(mockedContentManagementClient.search).toHaveBeenCalledWith( + expect.objectContaining({ + query: expect.objectContaining({ + text: 'Shiny dashboard*', + }), + }) + ); + + expect(onTitleDuplicate).toHaveBeenCalledWith(`${baseDashboardName} (15)`); + }); +}); diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.ts index 0ffcf8c9788e9..a4bd93191a487 100644 --- a/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.ts +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/check_for_duplicate_dashboard_title.ts @@ -9,12 +9,16 @@ import { DashboardStartDependencies } from '../../../plugin'; import { DASHBOARD_CONTENT_ID } from '../../../dashboard_constants'; import { DashboardCrudTypes } from '../../../../common/content_management'; +import { extractTitleAndCount } from '../../../dashboard_container/embeddable/api/lib/extract_title_and_count'; export interface DashboardDuplicateTitleCheckProps { title: string; copyOnSave: boolean; lastSavedTitle: string; - onTitleDuplicate?: () => void; + /** + * invokes the onTitleDuplicate function if provided with a speculative title that should be collision free + */ + onTitleDuplicate?: (speculativeSuggestion: string) => void; isTitleDuplicateConfirmed: boolean; } @@ -33,6 +37,11 @@ export async function checkForDuplicateDashboardTitle( }: DashboardDuplicateTitleCheckProps, contentManagement: DashboardStartDependencies['contentManagement'] ): Promise { + // Don't check if the title is an empty string + if (!title) { + return true; + } + // Don't check for duplicates if user has already confirmed save with duplicate title if (isTitleDuplicateConfirmed) { return true; @@ -44,21 +53,37 @@ export async function checkForDuplicateDashboardTitle( return true; } + const [baseDashboardName] = extractTitleAndCount(title); + const { hits } = await contentManagement.client.search< DashboardCrudTypes['SearchIn'], DashboardCrudTypes['SearchOut'] >({ contentTypeId: DASHBOARD_CONTENT_ID, query: { - text: title ? `${title}*` : undefined, - limit: 10, + text: `${baseDashboardName}*`, + limit: 20, + }, + options: { + onlyTitle: true, }, - options: { onlyTitle: true }, }); - const duplicate = hits.find((hit) => hit.attributes.title.toLowerCase() === title.toLowerCase()); + + const duplicate = Boolean( + hits.find((hit) => hit.attributes.title.toLowerCase() === title.toLowerCase()) + ); + if (!duplicate) { return true; } - onTitleDuplicate?.(); + + const [largestDuplicationId] = hits + .map((hit) => extractTitleAndCount(hit.attributes.title)[1]) + .sort((a, b) => b - a); + + const speculativeCollisionFreeTitle = `${baseDashboardName} (${largestDuplicationId + 1})`; + + onTitleDuplicate?.(speculativeCollisionFreeTitle); + return false; } diff --git a/test/functional/apps/dashboard/group4/dashboard_clone.ts b/test/functional/apps/dashboard/group4/dashboard_clone.ts index 1e15f4d44e740..25ad42ac10fe7 100644 --- a/test/functional/apps/dashboard/group4/dashboard_clone.ts +++ b/test/functional/apps/dashboard/group4/dashboard_clone.ts @@ -49,5 +49,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.dashboard.gotoDashboardLandingPage(); await listingTable.searchAndExpectItemsCount('dashboard', `${dashboardName} (2)`, 1); }); + + it('Clone should always increment from the last duplicated dashboard with a unique title', async function () { + await PageObjects.dashboard.loadSavedDashboard(clonedDashboardName); + // force dashboard duplicate id to increment out of logical progression bounds + await PageObjects.dashboard.duplicateDashboard(`${dashboardName} (20)`); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await listingTable.searchAndExpectItemsCount('dashboard', `${dashboardName} (20)`, 1); + // load dashboard with duplication id 1 + await PageObjects.dashboard.loadSavedDashboard(clonedDashboardName); + // run normal clone + await PageObjects.dashboard.duplicateDashboard(); + await PageObjects.dashboard.gotoDashboardLandingPage(); + // clone gets duplication id, that picks off from last duplicated dashboard + await listingTable.searchAndExpectItemsCount('dashboard', `${dashboardName} (21)`, 1); + }); }); } From 10de8203b8168d89e4e4bbe7192e0b7f313b09cd Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:47:52 +0100 Subject: [PATCH 064/127] [Security Solution][Detection Engine] fixes and unskips new terms FTR tests (#186283) ## Summary - addresses https://github.com/elastic/kibana/issues/180236 - replaces kibana expect with jest expect --- .../execution_logic/new_terms.ts | 168 +++++++++++------- 1 file changed, 104 insertions(+), 64 deletions(-) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts index d6f464b63d78d..9e2638981a9e8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts @@ -5,7 +5,7 @@ * 2.0. */ -import expect from '@kbn/expect'; +import expect from 'expect'; import { v4 as uuidv4 } from 'uuid'; import { NewTermsRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; @@ -80,8 +80,7 @@ export default ({ getService }: FtrProviderContext) => { return testId; }; - // Failing: See https://github.com/elastic/kibana/issues/180236 - describe.skip('@ess @serverless @serverlessQA New terms type rules', () => { + describe('@ess @serverless @serverlessQA New terms type rules', () => { before(async () => { await esArchiver.load(path); await esArchiver.load('x-pack/test/functional/es_archives/security_solution/new_terms'); @@ -110,8 +109,8 @@ export default ({ getService }: FtrProviderContext) => { const createdRule = await createRule(supertest, log, rule); const alerts = await getAlerts(supertest, log, es, createdRule); - expect(alerts.hits.hits.length).eql(1); - expect(removeRandomValuedPropertiesFromAlert(alerts.hits.hits[0]._source)).eql({ + expect(alerts.hits.hits.length).toEqual(1); + expect(removeRandomValuedPropertiesFromAlert(alerts.hits.hits[0]._source)).toEqual({ 'kibana.alert.new_terms': ['zeek-newyork-sha-aa8df15'], 'kibana.alert.rule.category': 'New Terms Rule', 'kibana.alert.rule.consumer': 'siem', @@ -145,12 +144,17 @@ export default ({ getService }: FtrProviderContext) => { version: '18.10 (Cosmic Cuttlefish)', }, }, - message: - 'Login by user root (UID: 0) on pts/0 (PID: 20638) from 8.42.77.171 (IP: 8.42.77.171)', + message: expect.stringMatching( + /Login by user (root|bob) \(UID: (0|1)\) on pts\/0 \(PID: 20638\) from 8\.42\.77\.171 \(IP: 8\.42\.77\.171\)/ + ), process: { pid: 20638 }, service: { type: 'system' }, source: { ip: '8.42.77.171' }, - user: { id: 0, name: 'root', terminal: 'pts/0' }, + user: { + id: expect.any(Number), + name: expect.stringMatching(/(root|bob)/), + terminal: 'pts/0', + }, 'event.action': 'user_login', 'event.category': 'authentication', 'event.dataset': 'login', @@ -162,7 +166,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.original_time': '2019-02-19T20:42:08.230Z', 'kibana.alert.ancestors': [ { - id: 'x07wJ2oB9v5HJNSHhyxi', + id: expect.any(String), type: 'event', index: 'auditbeat-8.0.0-2019.02.19-000001', depth: 0, @@ -173,8 +177,9 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.workflow_tags': [], 'kibana.alert.workflow_assignee_ids': [], 'kibana.alert.depth': 1, - 'kibana.alert.reason': - 'authentication event with source 8.42.77.171 by root on zeek-newyork-sha-aa8df15 created high alert Query with a rule id.', + 'kibana.alert.reason': expect.stringMatching( + /authentication event with source 8\.42\.77\.171 by (root|bob) on zeek-newyork-sha-aa8df15 created high alert Query with a rule id\./ + ), 'kibana.alert.severity': 'high', 'kibana.alert.risk_score': 55, 'kibana.alert.rule.parameters': { @@ -203,6 +208,9 @@ export default ({ getService }: FtrProviderContext) => { history_window_start: '2019-01-19T20:42:00.000Z', index: ['auditbeat-*'], language: 'kuery', + rule_source: { + type: 'internal', + }, }, 'kibana.alert.rule.actions': [], 'kibana.alert.rule.author': [], @@ -249,7 +257,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).contain(getMaxAlertsWarning()); + expect(logs[0].warnings).toContain(getMaxAlertsWarning()); }); it("doesn't generate max alerts warning when circuit breaker is met but not exceeded", async () => { @@ -262,7 +270,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).not.contain(getMaxAlertsWarning()); + expect(logs[0].warnings).not.toContain(getMaxAlertsWarning()); }); it('should generate 3 alerts when 1 document has 3 new values', async () => { @@ -276,19 +284,19 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(3); + expect(previewAlerts.length).toEqual(3); const previewAlertsOrderedByHostIp = orderBy( previewAlerts, '_source.kibana.alert.new_terms', 'asc' ); - expect(previewAlertsOrderedByHostIp[0]._source?.['kibana.alert.new_terms']).eql([ + expect(previewAlertsOrderedByHostIp[0]._source?.['kibana.alert.new_terms']).toEqual([ '10.10.0.6', ]); - expect(previewAlertsOrderedByHostIp[1]._source?.['kibana.alert.new_terms']).eql([ + expect(previewAlertsOrderedByHostIp[1]._source?.['kibana.alert.new_terms']).toEqual([ '157.230.208.30', ]); - expect(previewAlertsOrderedByHostIp[2]._source?.['kibana.alert.new_terms']).eql([ + expect(previewAlertsOrderedByHostIp[2]._source?.['kibana.alert.new_terms']).toEqual([ 'fe80::24ce:f7ff:fede:a571', ]); }); @@ -304,14 +312,14 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(3); + expect(previewAlerts.length).toEqual(3); const newTerms = orderBy( previewAlerts.map((item) => item._source?.['kibana.alert.new_terms']), ['0', '1'] ); - expect(newTerms).eql([ + expect(newTerms).toEqual([ ['zeek-newyork-sha-aa8df15', '10.10.0.6'], ['zeek-newyork-sha-aa8df15', '157.230.208.30'], ['zeek-newyork-sha-aa8df15', 'fe80::24ce:f7ff:fede:a571'], @@ -359,7 +367,7 @@ export default ({ getService }: FtrProviderContext) => { es, previewId: hostIpPreview.previewId, }); - expect(hostIpPreviewAlerts.length).eql(0); + expect(hostIpPreviewAlerts.length).toEqual(0); // shouldn't be terms for 'host.name' const hostNamePreview = await previewRule({ @@ -370,14 +378,14 @@ export default ({ getService }: FtrProviderContext) => { es, previewId: hostNamePreview.previewId, }); - expect(hostNamePreviewAlerts.length).eql(0); + expect(hostNamePreviewAlerts.length).toEqual(0); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(1); + expect(previewAlerts.length).toEqual(1); - expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).eql(['host-0', '127.0.0.2']); + expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).toEqual(['host-0', '127.0.0.2']); }); it('should generate 5 alerts, 1 for each new unique combination in 2 fields', async () => { @@ -416,14 +424,14 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(5); + expect(previewAlerts.length).toEqual(5); const newTerms = orderBy( previewAlerts.map((item) => item._source?.['kibana.alert.new_terms']), ['0', '1'] ); - expect(newTerms).eql([ + expect(newTerms).toEqual([ ['192.168.1.1', 'tag-new-1'], ['192.168.1.1', 'tag-new-3'], ['192.168.1.2', 'tag-2'], @@ -456,8 +464,8 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(1); - expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).eql(['user-0', '1']); + expect(previewAlerts.length).toEqual(1); + expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).toEqual(['user-0', 1]); }); it('should generate 1 alert for unique combination of terms, one of which is a boolean', async () => { @@ -472,8 +480,8 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(1); - expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).eql(['user-0', false]); + expect(previewAlerts.length).toEqual(1); + expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).toEqual(['user-0', false]); }); it('should generate alerts for every term when history window is small', async () => { @@ -488,15 +496,15 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(5); + expect(previewAlerts.length).toEqual(5); const hostNames = previewAlerts .map((signal) => signal._source?.['kibana.alert.new_terms']) .sort(); - expect(hostNames[0]).eql(['suricata-sensor-amsterdam']); - expect(hostNames[1]).eql(['suricata-sensor-san-francisco']); - expect(hostNames[2]).eql(['zeek-newyork-sha-aa8df15']); - expect(hostNames[3]).eql(['zeek-sensor-amsterdam']); - expect(hostNames[4]).eql(['zeek-sensor-san-francisco']); + expect(hostNames[0]).toEqual(['suricata-sensor-amsterdam']); + expect(hostNames[1]).toEqual(['suricata-sensor-san-francisco']); + expect(hostNames[2]).toEqual(['zeek-newyork-sha-aa8df15']); + expect(hostNames[3]).toEqual(['zeek-sensor-amsterdam']); + expect(hostNames[4]).toEqual(['zeek-sensor-san-francisco']); }); // github.com/elastic/kibana/issues/149920 @@ -538,9 +546,9 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(1); + expect(previewAlerts.length).toEqual(1); - expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).eql(['host-0', '127.0.0.2']); + expect(previewAlerts[0]._source?.['kibana.alert.new_terms']).toEqual(['host-0', '127.0.0.2']); }); describe('null values', () => { it('should not generate alerts with null values for single field', async () => { @@ -555,7 +563,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(0); + expect(previewAlerts.length).toEqual(0); }); it('should not generate alerts with null values for multiple fields', async () => { @@ -570,7 +578,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(0); + expect(previewAlerts.length).toEqual(0); }); }); @@ -587,7 +595,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: 100 }); - expect(previewAlerts.length).eql(20); + expect(previewAlerts.length).toEqual(20); }); // There is a limit in ES for a number of emitted values in runtime field (100) @@ -605,7 +613,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); - expect(previewAlerts.length).eql(100); + expect(previewAlerts.length).toEqual(100); }); // There is a limit in ES for a number of emitted values in runtime field (100) @@ -624,7 +632,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); - expect(previewAlerts.length).eql(100); + expect(previewAlerts.length).toEqual(100); }); it('should not miss alerts if rule execution value combinations number is greater than 100', async () => { @@ -672,7 +680,7 @@ export default ({ getService }: FtrProviderContext) => { const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); // 10 alerts (with host.names a-[0-9]) should be generated - expect(previewAlerts.length).eql(10); + expect(previewAlerts.length).toEqual(10); }); it('should not miss alerts for high cardinality values in arrays, over 10.000 composite page size', async () => { @@ -731,7 +739,7 @@ export default ({ getService }: FtrProviderContext) => { const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); // only 1 alert should be generated - expect(previewAlerts.length).eql(1); + expect(previewAlerts.length).toEqual(1); }); it('should not miss alerts for high cardinality values in arrays, over 10.000 composite page size spread over multiple pages', async () => { @@ -817,7 +825,7 @@ export default ({ getService }: FtrProviderContext) => { const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); // only 4 alerts should be generated - expect(previewAlerts.length).eql(4); + expect(previewAlerts.length).toEqual(4); }); it('should not generate false positive alerts if rule historical window combinations overlap execution ones, which have more than 100', async () => { @@ -867,7 +875,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); - expect(previewAlerts.length).eql(0); + expect(previewAlerts.length).toEqual(0); }); it('should not generate false positive alerts if rule historical window combinations overlap execution ones, which have precisely 100', async () => { @@ -911,7 +919,7 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: 200 }); - expect(previewAlerts.length).eql(0); + expect(previewAlerts.length).toEqual(0); }); }); @@ -949,12 +957,12 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(2); + expect(previewAlerts.length).toEqual(2); const hostNames = previewAlerts .map((signal) => signal._source?.['kibana.alert.new_terms']) .sort(); - expect(hostNames[0]).eql(['host-3']); - expect(hostNames[1]).eql(['host-4']); + expect(hostNames[0]).toEqual(['host-3']); + expect(hostNames[1]).toEqual(['host-4']); }); }); @@ -989,14 +997,14 @@ export default ({ getService }: FtrProviderContext) => { }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).eql(4); + expect(previewAlerts.length).toEqual(4); const hostNames = previewAlerts .map((signal) => signal._source?.['kibana.alert.new_terms']) .sort(); - expect(hostNames[0]).eql(['suricata-sensor-amsterdam']); - expect(hostNames[1]).eql(['suricata-sensor-san-francisco']); - expect(hostNames[2]).eql(['zeek-newyork-sha-aa8df15']); - expect(hostNames[3]).eql(['zeek-sensor-amsterdam']); + expect(hostNames[0]).toEqual(['suricata-sensor-amsterdam']); + expect(hostNames[1]).toEqual(['suricata-sensor-san-francisco']); + expect(hostNames[2]).toEqual(['zeek-newyork-sha-aa8df15']); + expect(hostNames[3]).toEqual(['zeek-sensor-amsterdam']); }); }); @@ -1014,11 +1022,11 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxAlerts * 2 }); - expect(previewAlerts.length).eql(maxAlerts); + expect(previewAlerts.length).toEqual(maxAlerts); const processPids = previewAlerts .map((signal) => signal._source?.['kibana.alert.new_terms']) .sort(); - expect(processPids[0]).eql([1]); + expect(processPids[0]).toEqual([1]); }); describe('alerts should be be enriched', () => { @@ -1041,13 +1049,14 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts[0]?._source?.host?.risk?.calculated_level).to.eql('Low'); - expect(previewAlerts[0]?._source?.host?.risk?.calculated_score_norm).to.eql(23); + expect(previewAlerts[0]?._source?.host?.risk?.calculated_level).toEqual('Low'); + expect(previewAlerts[0]?._source?.host?.risk?.calculated_score_norm).toEqual(23); }); }); describe('with asset criticality', async () => { before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/ecs_compliant'); await esArchiver.load('x-pack/test/functional/es_archives/asset_criticality'); await kibanaServer.uiSettings.update({ [ENABLE_ASSET_CRITICALITY_SETTING]: true, @@ -1055,23 +1064,54 @@ export default ({ getService }: FtrProviderContext) => { }); after(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/ecs_compliant' + ); await esArchiver.unload('x-pack/test/functional/es_archives/asset_criticality'); }); + const { indexListOfDocuments } = dataGeneratorFactory({ + es, + index: 'ecs_compliant', + log, + }); + it('should be enriched alert with criticality_level', async () => { + const id = uuidv4(); + const timestamp = '2020-10-28T06:45:00.000Z'; + + const firstExecutionDocuments = [ + { + host: { name: 'zeek-newyork-sha-aa8df15', ip: '127.0.0.5' }, + user: { name: 'root' }, + id, + '@timestamp': timestamp, + }, + ]; + + await indexListOfDocuments([...firstExecutionDocuments]); + const rule: NewTermsRuleCreateProps = { ...getCreateNewTermsRulesSchemaMock('rule-1', true), new_terms_fields: ['host.name'], - from: '2019-02-19T20:42:00.000Z', - history_window_start: '2019-01-19T20:42:00.000Z', + query: `id: "${id}"`, + index: ['ecs_compliant'], + history_window_start: '2019-10-13T05:00:04.000Z', + from: 'now-35m', + interval: '30m', }; - const { previewId } = await previewRule({ supertest, rule }); + const { previewId } = await previewRule({ + supertest, + rule, + timeframeEnd: new Date('2020-10-28T07:00:00.000Z'), + }); const previewAlerts = await getPreviewAlerts({ es, previewId }); + expect(previewAlerts.length).toBe(1); const fullAlert = previewAlerts[0]._source; - expect(fullAlert?.['host.asset.criticality']).to.eql('medium_impact'); - expect(fullAlert?.['user.asset.criticality']).to.eql('extreme_impact'); + expect(fullAlert?.['host.asset.criticality']).toBe('medium_impact'); + expect(fullAlert?.['user.asset.criticality']).toBe('extreme_impact'); }); }); }); From 63ceab2376cef3e79d811831bb846c53cf4b83d2 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 18 Jun 2024 12:54:03 -0400 Subject: [PATCH 065/127] feat(slo): Improve permission check on SLO pages (#182609) --- .../slo/slo_permissions_callout/index.tsx | 97 ++++++++++ .../hooks/use_fetch_global_diagnosis.ts | 10 +- .../slo/public/hooks/use_fetch_slo_list.ts | 1 + .../slo/public/hooks/use_permissions.test.ts | 169 ++++++++++++++++++ .../slo/public/hooks/use_permissions.ts | 43 +++++ .../slo_details/components/header_control.tsx | 16 +- .../pages/slo_details/slo_details.test.tsx | 36 +++- .../public/pages/slo_details/slo_details.tsx | 16 +- .../public/pages/slo_edit/slo_edit.test.tsx | 91 ++++++---- .../slo/public/pages/slo_edit/slo_edit.tsx | 27 +-- .../pages/slo_outdated_definitions/index.tsx | 29 ++- .../slos/components/common/create_slo_btn.tsx | 6 +- .../compact_view/slo_list_compact_view.tsx | 19 +- .../slos/components/slo_item_actions.tsx | 16 +- .../slo/public/pages/slos/slos.test.tsx | 32 +++- .../slo/public/pages/slos/slos.tsx | 16 +- .../pages/slos_welcome/slos_welcome.test.tsx | 64 ++++--- .../pages/slos_welcome/slos_welcome.tsx | 50 +++--- .../slo/server/services/get_diagnosis.ts | 2 +- 19 files changed, 556 insertions(+), 184 deletions(-) create mode 100644 x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx create mode 100644 x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.test.ts create mode 100644 x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.ts diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx new file mode 100644 index 0000000000000..720f31ccea3fa --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx @@ -0,0 +1,97 @@ +/* + * Copyright 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 { EuiCallOut, EuiSpacer, EuiLink, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { usePermissions } from '../../../hooks/use_permissions'; + +export function SloPermissionsCallout() { + const { data: permissions, isLoading } = usePermissions(); + + if (isLoading) { + return null; + } + + if (permissions?.hasAllReadRequested || permissions?.hasAllWriteRequested) { + return null; + } + + return ( + <> + + + + + + + +
    +
  • + +
  • +
+
+ + + + +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ + + {i18n.translate('xpack.slo.permissionsCallout.readDocumentation', { + defaultMessage: 'Read the documentation for more details', + })} + +
+
+ + + ); +} diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_global_diagnosis.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_global_diagnosis.ts index 22862110910da..df8ea83ed2aaa 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_global_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_global_diagnosis.ts @@ -19,11 +19,7 @@ interface SloGlobalDiagnosisResponse { } export interface UseFetchSloGlobalDiagnoseResponse { - isInitialLoading: boolean; isLoading: boolean; - isRefetching: boolean; - isSuccess: boolean; - isError: boolean; data: SloGlobalDiagnosisResponse | undefined; } @@ -33,7 +29,7 @@ export function useFetchSloGlobalDiagnosis(): UseFetchSloGlobalDiagnoseResponse notifications: { toasts }, } = useKibana().services; - const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + const { isLoading, data } = useQuery({ queryKey: sloKeys.globalDiagnosis(), queryFn: async ({ signal }) => { try { @@ -65,9 +61,5 @@ export function useFetchSloGlobalDiagnosis(): UseFetchSloGlobalDiagnoseResponse return { data, isLoading, - isInitialLoading, - isRefetching, - isSuccess, - isError, }; } diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slo_list.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slo_list.ts index 289c8e5cbd418..0e2bb39dab878 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_slo_list.ts @@ -115,6 +115,7 @@ export function useFetchSloList({ if (String(error) === 'Error: Forbidden') { return false; } + return failureCount < 4; }, onSuccess: ({ results }: FindSLOResponse) => { diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.test.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.test.ts new file mode 100644 index 0000000000000..c9646c070dbbb --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.test.ts @@ -0,0 +1,169 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { sloFeatureId } from '@kbn/observability-shared-plugin/common'; +import { useKibana } from '../utils/kibana_react'; +import { useFetchSloGlobalDiagnosis } from './use_fetch_global_diagnosis'; +import { usePermissions } from './use_permissions'; + +jest.mock('../utils/kibana_react'); +jest.mock('./use_fetch_global_diagnosis'); + +const useKibanaMock = useKibana as jest.Mock; +const useFetchSloGlobalDiagnosisMock = useFetchSloGlobalDiagnosis as jest.Mock; + +describe('usePermissions', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('is loading until diagnosis is done', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: true, write: true } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: undefined, + isLoading: true, + }); + + const { data, isLoading } = usePermissions(); + + expect(isLoading).toBe(true); + expect(data).toBe(undefined); + }); + + describe('hasAllReadRequested', () => { + it('returns hasAllReadRequested = true when both write capabilities and read privileges are true', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: true, write: false } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: { + userPrivileges: { + read: { has_all_requested: true }, + write: { has_all_requested: false }, + }, + }, + isLoading: false, + }); + + const { data } = usePermissions(); + + expect(data?.hasAllReadRequested).toBe(true); + }); + + it('returns hasAllReadRequested = false when read capabilities is false and read privileges is true', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: false, write: false } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: { + userPrivileges: { + read: { has_all_requested: true }, + write: { has_all_requested: false }, + }, + }, + isLoading: false, + }); + + const { data } = usePermissions(); + + expect(data?.hasAllReadRequested).toBe(false); + }); + + it('returns hasAllReadRequested = false when read capabilities is true and read privileges is false', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: true, write: false } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: { + userPrivileges: { + read: { has_all_requested: false }, + write: { has_all_requested: false }, + }, + }, + isLoading: false, + }); + + const { data } = usePermissions(); + + expect(data?.hasAllReadRequested).toBe(false); + }); + }); + + describe('hasAllWriteRequested', () => { + it('returns hasAllWriteRequested = true when both write capabilities and write privileges are true', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: false, write: true } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: { + userPrivileges: { + read: { has_all_requested: false }, + write: { has_all_requested: true }, + }, + }, + isLoading: false, + }); + + const { data } = usePermissions(); + + expect(data?.hasAllWriteRequested).toBe(true); + }); + + it('returns hasAllWriteRequested = false when write capabilities is false and write privileges is true', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: false, write: false } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: { + userPrivileges: { + read: { has_all_requested: false }, + write: { has_all_requested: true }, + }, + }, + isLoading: false, + }); + + const { data } = usePermissions(); + + expect(data?.hasAllWriteRequested).toBe(false); + }); + + it('returns hasAllWriteRequested = false when write capabilities is true and write privileges is false', () => { + useKibanaMock.mockReturnValue({ + services: { + application: { capabilities: { [sloFeatureId]: { read: false, write: true } } }, + }, + }); + useFetchSloGlobalDiagnosisMock.mockReturnValue({ + data: { + userPrivileges: { + read: { has_all_requested: false }, + write: { has_all_requested: false }, + }, + }, + isLoading: false, + }); + + const { data } = usePermissions(); + + expect(data?.hasAllWriteRequested).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.ts new file mode 100644 index 0000000000000..6e380fbe1a33e --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_permissions.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { sloFeatureId } from '@kbn/observability-plugin/common'; +import { useKibana } from '../utils/kibana_react'; +import { useFetchSloGlobalDiagnosis } from './use_fetch_global_diagnosis'; + +export function usePermissions() { + const { + application: { capabilities }, + } = useKibana().services; + + const { data: globalDiagnosis, isLoading } = useFetchSloGlobalDiagnosis(); + + const hasRequiredReadCapabilities = !!capabilities[sloFeatureId].read ?? false; + const hasRequiredWriteCapabilities = !!capabilities[sloFeatureId].write ?? false; + + const hasRequiredReadPrivileges = + !!globalDiagnosis?.userPrivileges.read.has_all_requested ?? false; + const hasRequiredWritePrivileges = + !!globalDiagnosis?.userPrivileges.write.has_all_requested ?? false; + + return { + isLoading, + data: isLoading + ? undefined + : { + capabilities: { + read: hasRequiredReadCapabilities, + write: hasRequiredWriteCapabilities, + }, + privileges: { + read: hasRequiredReadPrivileges, + write: hasRequiredWritePrivileges, + }, + hasAllReadRequested: hasRequiredReadCapabilities && hasRequiredReadPrivileges, + hasAllWriteRequested: hasRequiredWriteCapabilities && hasRequiredWritePrivileges, + }, + }; +} diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/header_control.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/header_control.tsx index 6239984922406..fb1e524e3e170 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/header_control.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/header_control.tsx @@ -20,9 +20,9 @@ import React, { useCallback, useEffect, useState } from 'react'; import { paths } from '../../../../common/locators/paths'; import { SloDeleteModal } from '../../../components/slo/delete_confirmation_modal/slo_delete_confirmation_modal'; import { SloResetConfirmationModal } from '../../../components/slo/reset_confirmation_modal/slo_reset_confirmation_modal'; -import { useCapabilities } from '../../../hooks/use_capabilities'; import { useCloneSlo } from '../../../hooks/use_clone_slo'; import { useFetchRulesForSlo } from '../../../hooks/use_fetch_rules_for_slo'; +import { usePermissions } from '../../../hooks/use_permissions'; import { useResetSlo } from '../../../hooks/use_reset_slo'; import { useKibana } from '../../../utils/kibana_react'; import { convertSliApmParamsToApmAppDeeplinkUrl } from '../../../utils/slo/convert_sli_apm_params_to_apm_app_deeplink_url'; @@ -44,7 +44,7 @@ export function HeaderControl({ isLoading, slo }: Props) { } = useKibana().services; const hasApmReadCapabilities = capabilities.apm.show; - const { hasWriteCapabilities } = useCapabilities(); + const { data: permissions } = usePermissions(); const { isDeletingSlo, isResettingSlo, removeDeleteQueryParam, removeResetQueryParam } = useGetQueryParams(); @@ -198,7 +198,7 @@ export function HeaderControl({ isLoading, slo }: Props) { items={[ , , ({ ...jest.requireActual('react-router-dom'), @@ -42,7 +42,7 @@ jest.mock('react-router-dom', () => ({ jest.mock('@kbn/observability-shared-plugin/public'); jest.mock('../../utils/kibana_react'); jest.mock('../../hooks/use_license'); -jest.mock('../../hooks/use_capabilities'); +jest.mock('../../hooks/use_permissions'); jest.mock('../../hooks/use_fetch_active_alerts'); jest.mock('../../hooks/use_fetch_slo_details'); jest.mock('../../hooks/use_fetch_historical_summary'); @@ -53,7 +53,7 @@ jest.mock('../../hooks/use_delete_slo_instance'); const useKibanaMock = useKibana as jest.Mock; const useLicenseMock = useLicense as jest.Mock; -const useCapabilitiesMock = useCapabilities as jest.Mock; +const usePermissionsMock = usePermissions as jest.Mock; const useFetchActiveAlertsMock = useFetchActiveAlerts as jest.Mock; const useFetchSloDetailsMock = useFetchSloDetails as jest.Mock; const useFetchHistoricalSummaryMock = useFetchHistoricalSummary as jest.Mock; @@ -134,7 +134,10 @@ describe('SLO Details Page', () => { beforeEach(() => { jest.clearAllMocks(); mockKibana(); - useCapabilitiesMock.mockReturnValue({ hasWriteCapabilities: true, hasReadCapabilities: true }); + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { hasAllReadRequested: true, hasAllWriteRequested: true }, + }); useCreateDataViewsMock.mockReturnValue({ dataView: { getName: () => 'dataview', getIndexPattern: () => '.dataview-index' }, }); @@ -151,7 +154,7 @@ describe('SLO Details Page', () => { }); describe('when the incorrect license is found', () => { - it('navigates to the SLO List page', async () => { + it('navigates to the SLO welcome page', async () => { const slo = buildSlo(); jest.spyOn(Router, 'useParams').mockReturnValue({ sloId: slo.id }); useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); @@ -159,7 +162,24 @@ describe('SLO Details Page', () => { render(); - expect(mockNavigate).toBeCalledWith(paths.slos); + expect(mockNavigate).toBeCalledWith(paths.slosWelcome); + }); + }); + + describe('when the user has not the requested read permissions ', () => { + it('navigates to the slos welcome page', async () => { + const slo = buildSlo(); + jest.spyOn(Router, 'useParams').mockReturnValue({ sloId: slo.id }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); + useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { hasAllReadRequested: false, hasAllWriteRequested: false }, + }); + + render(); + + expect(mockNavigate).toBeCalledWith(paths.slosWelcome); }); }); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx index 2c3cf109fa89f..3da2e0f991109 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/slo_details.tsx @@ -21,6 +21,7 @@ import { AutoRefreshButton } from '../../components/slo/auto_refresh_button'; import { useAutoRefreshStorage } from '../../components/slo/auto_refresh_button/hooks/use_auto_refresh_storage'; import { useFetchSloDetails } from '../../hooks/use_fetch_slo_details'; import { useLicense } from '../../hooks/use_license'; +import { usePermissions } from '../../hooks/use_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { useKibana } from '../../utils/kibana_react'; import PageNotFound from '../404'; @@ -41,6 +42,7 @@ export function SloDetailsPage() { const { ObservabilityPageTemplate } = usePluginContext(); const { hasAtLeast } = useLicense(); const hasRightLicense = hasAtLeast('platinum'); + const { data: permissions } = usePermissions(); const { sloId } = useParams(); const { instanceId: sloInstanceId, remoteName } = useGetQueryParams(); @@ -62,8 +64,6 @@ export function SloDetailsPage() { selectedTabId, }); - useBreadcrumbs(getBreadcrumbs(basePath, slo)); - useEffect(() => { if (!slo || !observabilityAIAssistant) { return; @@ -90,15 +90,19 @@ export function SloDetailsPage() { }); }, [observabilityAIAssistant, slo]); + useEffect(() => { + if (hasRightLicense === false || permissions?.hasAllReadRequested === false) { + navigateToUrl(basePath.prepend(paths.slosWelcome)); + } + }, [hasRightLicense, permissions, navigateToUrl, basePath]); + + useBreadcrumbs(getBreadcrumbs(basePath, slo)); + const isSloNotFound = !isLoading && slo === undefined; if (isSloNotFound) { return ; } - if (hasRightLicense === false) { - navigateToUrl(basePath.prepend(paths.slos)); - } - const isPerformingAction = isLoading || isDeleting; const handleToggleAutoRefresh = () => { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx index 5f6916720902b..03838225d1618 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx @@ -8,6 +8,8 @@ import { ILicense } from '@kbn/licensing-plugin/common/types'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assistant-plugin/public/mock'; +import { useCreateRule, useFetchDataViews } from '@kbn/observability-plugin/public'; +import { HeaderMenuPortal } from '@kbn/observability-shared-plugin/public'; import { cleanup, fireEvent, waitFor } from '@testing-library/react'; import { createBrowserHistory } from 'history'; import React from 'react'; @@ -15,20 +17,18 @@ import Router from 'react-router-dom'; import { BehaviorSubject } from 'rxjs'; import { paths } from '../../../common/locators/paths'; import { buildSlo } from '../../data/slo/slo'; -import { useCapabilities } from '../../hooks/use_capabilities'; +import { useCreateDataView } from '../../hooks/use_create_data_view'; import { useCreateSlo } from '../../hooks/use_create_slo'; import { useFetchApmSuggestions } from '../../hooks/use_fetch_apm_suggestions'; +import { useFetchIndices } from '../../hooks/use_fetch_indices'; import { useFetchSloDetails } from '../../hooks/use_fetch_slo_details'; +import { usePermissions } from '../../hooks/use_permissions'; import { useUpdateSlo } from '../../hooks/use_update_slo'; -import { useCreateRule, useFetchDataViews } from '@kbn/observability-plugin/public'; -import { useCreateDataView } from '../../hooks/use_create_data_view'; -import { useFetchIndices } from '../../hooks/use_fetch_indices'; import { useKibana } from '../../utils/kibana_react'; import { kibanaStartMock } from '../../utils/kibana_react.mock'; import { render } from '../../utils/test_helper'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from './constants'; import { SloEditPage } from './slo_edit'; -import { HeaderMenuPortal } from '@kbn/observability-shared-plugin/public'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -36,14 +36,14 @@ jest.mock('react-router-dom', () => ({ })); jest.mock('@kbn/observability-shared-plugin/public'); +jest.mock('@kbn/observability-plugin/public'); jest.mock('../../hooks/use_fetch_indices'); jest.mock('../../hooks/use_create_data_view'); jest.mock('../../hooks/use_fetch_slo_details'); jest.mock('../../hooks/use_create_slo'); jest.mock('../../hooks/use_update_slo'); -jest.mock('@kbn/observability-plugin/public'); jest.mock('../../hooks/use_fetch_apm_suggestions'); -jest.mock('../../hooks/use_capabilities'); +jest.mock('../../hooks/use_permissions'); const mockUseKibanaReturnValue = kibanaStartMock.startContract(); @@ -54,13 +54,13 @@ jest.mock('../../utils/kibana_react', () => ({ const useKibanaMock = useKibana as jest.Mock; const useFetchIndicesMock = useFetchIndices as jest.Mock; const useFetchDataViewsMock = useFetchDataViews as jest.Mock; -const useCreateDataViewsMock = useCreateDataView as jest.Mock; +const useCreateDataViewMock = useCreateDataView as jest.Mock; const useFetchSloMock = useFetchSloDetails as jest.Mock; const useCreateSloMock = useCreateSlo as jest.Mock; const useUpdateSloMock = useUpdateSlo as jest.Mock; const useCreateRuleMock = useCreateRule as jest.Mock; const useFetchApmSuggestionsMock = useFetchApmSuggestions as jest.Mock; -const useCapabilitiesMock = useCapabilities as jest.Mock; +const usePermissionsMock = usePermissions as jest.Mock; const HeaderMenuPortalMock = HeaderMenuPortal as jest.Mock; HeaderMenuPortalMock.mockReturnValue(
Portal node
); @@ -77,12 +77,14 @@ const mockKibana = (license: ILicense | null = licenseMock) => { theme: {}, application: { navigateToUrl: mockNavigate, + capabilities: {}, }, charts: { theme: { useChartsBaseTheme: () => {}, }, }, + dataViewEditor: {}, data: { dataViews: { find: jest.fn().mockReturnValue([]), @@ -164,18 +166,20 @@ describe('SLO Edit Page', () => { data: [ { getName: () => 'dataview', - getIndexPattern: () => '.dataview-index', + getIndexPattern: () => 'some-index', getRuntimeMappings: jest.fn().mockReturnValue({}), }, ], }); - useCreateDataViewsMock.mockReturnValue({ + useCreateDataViewMock.mockReturnValue({ dataView: { getName: () => 'dataview', - getIndexPattern: () => '.dataview-index', + getIndexPattern: () => 'some-index', getRuntimeMappings: jest.fn().mockReturnValue({}), + fields: [{ name: 'custom_timestamp', type: 'date' }], }, + loading: false, }); useFetchIndicesMock.mockReturnValue({ @@ -203,16 +207,21 @@ describe('SLO Edit Page', () => { isError: false, mutateAsync: mockUpdate, }); + + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { + hasAllWriteRequested: true, + hasAllReadRequested: true, + }, + }); + licenseMock.hasAtLeast.mockReturnValue(true); }); afterEach(cleanup); describe('when the incorrect license is found', () => { beforeEach(() => { - useCapabilitiesMock.mockReturnValue({ - hasWriteCapabilities: true, - hasReadCapabilities: true, - }); licenseMock.hasAtLeast.mockReturnValue(false); }); @@ -232,10 +241,6 @@ describe('SLO Edit Page', () => { describe('when the license is null', () => { beforeEach(() => { - useCapabilitiesMock.mockReturnValue({ - hasWriteCapabilities: true, - hasReadCapabilities: true, - }); mockKibana(null); }); @@ -255,18 +260,17 @@ describe('SLO Edit Page', () => { describe('when the correct license is found', () => { beforeEach(() => { - useCapabilitiesMock.mockReturnValue({ - hasWriteCapabilities: true, - hasReadCapabilities: true, - }); licenseMock.hasAtLeast.mockReturnValue(true); }); describe('with no write permission', () => { beforeEach(() => { - useCapabilitiesMock.mockReturnValue({ - hasWriteCapabilities: false, - hasReadCapabilities: true, + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { + hasAllWriteRequested: false, + hasAllReadRequested: true, + }, }); }); @@ -284,6 +288,31 @@ describe('SLO Edit Page', () => { }); }); + describe('with no read permission', () => { + beforeEach(() => { + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { + hasAllWriteRequested: false, + hasAllReadRequested: false, + }, + }); + }); + + it('redirects to the slo welcome page', async () => { + jest.spyOn(Router, 'useParams').mockReturnValue({ sloId: '1234' }); + jest + .spyOn(Router, 'useLocation') + .mockReturnValue({ pathname: '/slos/1234/edit', search: '', state: '', hash: '' }); + + useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); + + render(); + + expect(mockNavigate).toBeCalledWith(mockBasePathPrepend(paths.slosWelcome)); + }); + }); + describe('when no sloId route param is provided', () => { beforeEach(() => { useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); @@ -345,7 +374,7 @@ describe('SLO Edit Page', () => { describe('when a sloId route param is provided', () => { it('prefills the form with the SLO values', async () => { const slo = buildSlo({ id: '123Foo' }); - useFetchSloMock.mockReturnValue({ isLoading: false, isInitialLoading: false, data: slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); jest.spyOn(Router, 'useParams').mockReturnValue({ sloId: '123Foo' }); jest @@ -429,7 +458,6 @@ describe('SLO Edit Page', () => { describe('when submitting has completed successfully', () => { it('navigates to the SLO List page', async () => { const slo = buildSlo(); - jest.spyOn(Router, 'useParams').mockReturnValue({ sloId: '123' }); jest .spyOn(Router, 'useLocation') @@ -444,9 +472,8 @@ describe('SLO Edit Page', () => { await waitFor(() => { fireEvent.click(getByTestId('sloFormSubmitButton')); }); - await waitFor(() => { - expect(mockNavigate).toBeCalledWith(mockBasePathPrepend(paths.slos)); - }); + + expect(mockNavigate).toBeCalledWith(mockBasePathPrepend(paths.slos)); }); }); }); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx index 09f3b257e6542..aa008838a8b3c 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.tsx @@ -7,16 +7,15 @@ import { i18n } from '@kbn/i18n'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; -import React from 'react'; +import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; -import { HeaderMenu } from '../../components/header_menu/header_menu'; -import { useKibana } from '../../utils/kibana_react'; import { paths } from '../../../common/locators/paths'; -import { useCapabilities } from '../../hooks/use_capabilities'; -import { useFetchSloGlobalDiagnosis } from '../../hooks/use_fetch_global_diagnosis'; +import { HeaderMenu } from '../../components/header_menu/header_menu'; import { useFetchSloDetails } from '../../hooks/use_fetch_slo_details'; import { useLicense } from '../../hooks/use_license'; +import { usePermissions } from '../../hooks/use_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; +import { useKibana } from '../../utils/kibana_react'; import { SloEditForm } from './components/slo_edit_form'; export function SloEditPage() { @@ -24,11 +23,11 @@ export function SloEditPage() { application: { navigateToUrl }, http: { basePath }, } = useKibana().services; - const { hasWriteCapabilities } = useCapabilities(); - const { isError: hasErrorInGlobalDiagnosis } = useFetchSloGlobalDiagnosis(); + const { sloId } = useParams<{ sloId: string | undefined }>(); + + const { data: permissions } = usePermissions(); const { ObservabilityPageTemplate } = usePluginContext(); - const { sloId } = useParams<{ sloId: string | undefined }>(); const { hasAtLeast } = useLicense(); const hasRightLicense = hasAtLeast('platinum'); const { data: slo } = useFetchSloDetails({ sloId }); @@ -60,9 +59,15 @@ export function SloEditPage() { }, ]); - if (hasRightLicense === false || !hasWriteCapabilities || hasErrorInGlobalDiagnosis) { - navigateToUrl(basePath.prepend(paths.slos)); - } + useEffect(() => { + if (hasRightLicense === false || permissions?.hasAllReadRequested === false) { + navigateToUrl(basePath.prepend(paths.slosWelcome)); + } + + if (permissions?.hasAllWriteRequested === false) { + navigateToUrl(basePath.prepend(paths.slos)); + } + }, [hasRightLicense, permissions, navigateToUrl, basePath]); return ( {i18n.translate('xpack.slo.slosOutdatedDefinitions.sloPermissionsError', { @@ -96,7 +89,7 @@ export function SlosOutdatedDefinitions() { > - {!hasSlosAndHasPermissions ? ( + {!!errors ? ( errors ) : ( <> diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/create_slo_btn.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/create_slo_btn.tsx index 14701ef9e4f60..7add8debe165b 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/create_slo_btn.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/create_slo_btn.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useKibana } from '../../../../utils/kibana_react'; import { paths } from '../../../../../common/locators/paths'; -import { useCapabilities } from '../../../../hooks/use_capabilities'; +import { usePermissions } from '../../../../hooks/use_permissions'; export function CreateSloBtn() { const { @@ -18,7 +18,7 @@ export function CreateSloBtn() { http: { basePath }, } = useKibana().services; - const { hasWriteCapabilities } = useCapabilities(); + const { data: permissions } = usePermissions(); const handleClickCreateSlo = () => { navigateToUrl(basePath.prepend(paths.sloCreate)); @@ -27,7 +27,7 @@ export function CreateSloBtn() { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/compact_view/slo_list_compact_view.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/compact_view/slo_list_compact_view.tsx index d773d56ac47f8..0d556c0546e1f 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/compact_view/slo_list_compact_view.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/compact_view/slo_list_compact_view.tsx @@ -28,12 +28,12 @@ import { SloResetConfirmationModal } from '../../../../components/slo/reset_conf import { SloStatusBadge } from '../../../../components/slo/slo_status_badge'; import { SloActiveAlertsBadge } from '../../../../components/slo/slo_status_badge/slo_active_alerts_badge'; import { sloKeys } from '../../../../hooks/query_key_factory'; -import { useCapabilities } from '../../../../hooks/use_capabilities'; import { useCloneSlo } from '../../../../hooks/use_clone_slo'; import { useFetchActiveAlerts } from '../../../../hooks/use_fetch_active_alerts'; import { useFetchHistoricalSummary } from '../../../../hooks/use_fetch_historical_summary'; import { useFetchRulesForSlo } from '../../../../hooks/use_fetch_rules_for_slo'; import { useGetFilteredRuleTypes } from '../../../../hooks/use_get_filtered_rule_types'; +import { usePermissions } from '../../../../hooks/use_permissions'; import { useResetSlo } from '../../../../hooks/use_reset_slo'; import { useSpace } from '../../../../hooks/use_space'; import { useKibana } from '../../../../utils/kibana_react'; @@ -74,7 +74,7 @@ export function SloListCompactView({ sloList, loading, error }: Props) { (slo) => [slo.id, slo.instanceId ?? ALL_VALUE] as [string, string] ); - const { hasWriteCapabilities } = useCapabilities(); + const { data: permissions } = usePermissions(); const filteredRuleTypes = useGetFilteredRuleTypes(); const queryClient = useQueryClient(); @@ -173,7 +173,8 @@ export function SloListCompactView({ sloList, loading, error }: Props) { defaultMessage: 'Edit', }), 'data-test-subj': 'sloActionsEdit', - enabled: (slo) => (hasWriteCapabilities && !isRemote(slo)) || hasRemoteKibanaUrl(slo), + enabled: (slo) => + (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo), onClick: (slo: SLOWithSummaryResponse) => { const remoteEditUrl = createRemoteSloEditUrl(slo, spaceId); if (!!remoteEditUrl) { @@ -193,7 +194,8 @@ export function SloListCompactView({ sloList, loading, error }: Props) { defaultMessage: 'Create new alert rule', }), 'data-test-subj': 'sloActionsCreateRule', - enabled: (slo: SLOWithSummaryResponse) => hasWriteCapabilities && !isRemote(slo), + enabled: (slo: SLOWithSummaryResponse) => + !!permissions?.hasAllWriteRequested && !isRemote(slo), onClick: (slo: SLOWithSummaryResponse) => { setSloToAddRule(slo); }, @@ -208,7 +210,8 @@ export function SloListCompactView({ sloList, loading, error }: Props) { defaultMessage: 'Manage rules', }), 'data-test-subj': 'sloActionsManageRules', - enabled: (slo: SLOWithSummaryResponse) => hasWriteCapabilities && !isRemote(slo), + enabled: (slo: SLOWithSummaryResponse) => + !!permissions?.hasAllWriteRequested && !isRemote(slo), onClick: (slo: SLOWithSummaryResponse) => { const locator = locators.get(rulesLocatorID); locator?.navigate({ params: { sloId: slo.id } }, { replace: false }); @@ -227,7 +230,7 @@ export function SloListCompactView({ sloList, loading, error }: Props) { }), 'data-test-subj': 'sloActionsClone', enabled: (slo: SLOWithSummaryResponse) => - (hasWriteCapabilities && !isRemote(slo)) || hasRemoteKibanaUrl(slo), + (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo), onClick: (slo: SLOWithSummaryResponse) => { navigateToClone(slo); }, @@ -245,7 +248,7 @@ export function SloListCompactView({ sloList, loading, error }: Props) { }), 'data-test-subj': 'sloActionsDelete', enabled: (slo: SLOWithSummaryResponse) => - (hasWriteCapabilities && !isRemote(slo)) || hasRemoteKibanaUrl(slo), + (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo), onClick: (slo: SLOWithSummaryResponse) => { const remoteDeleteUrl = createRemoteSloDeleteUrl(slo, spaceId); if (!!remoteDeleteUrl) { @@ -268,7 +271,7 @@ export function SloListCompactView({ sloList, loading, error }: Props) { }), 'data-test-subj': 'sloActionsReset', enabled: (slo: SLOWithSummaryResponse) => - (hasWriteCapabilities && !isRemote(slo)) || hasRemoteKibanaUrl(slo), + (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo), onClick: (slo: SLOWithSummaryResponse) => { const remoteResetUrl = createRemoteSloResetUrl(slo, spaceId); if (!!remoteResetUrl) { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_item_actions.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_item_actions.tsx index a5de471bae883..b3b6dbc645a2c 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_item_actions.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_item_actions.tsx @@ -19,7 +19,7 @@ import { SLOWithSummaryResponse } from '@kbn/slo-schema'; import { Rule } from '@kbn/triggers-actions-ui-plugin/public'; import React from 'react'; import styled from 'styled-components'; -import { useCapabilities } from '../../../hooks/use_capabilities'; +import { usePermissions } from '../../../hooks/use_permissions'; import { useCloneSlo } from '../../../hooks/use_clone_slo'; import { BurnRateRuleParams } from '../../../typings'; import { useKibana } from '../../../utils/kibana_react'; @@ -76,7 +76,7 @@ export function SloItemActions({ } = useKibana().services; const executionContextName = executionContext.get().name; const isDashboardContext = executionContextName === 'dashboards'; - const { hasWriteCapabilities } = useCapabilities(); + const { data: permissions } = usePermissions(); const navigateToClone = useCloneSlo(); const { handleNavigateToRules, sloEditUrl, remoteDeleteUrl, remoteResetUrl, sloDetailsUrl } = @@ -182,7 +182,7 @@ export function SloItemActions({ , { selectedRemoteClusters: [], }, }); - useCapabilitiesMock.mockReturnValue({ hasWriteCapabilities: true, hasReadCapabilities: true }); + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { hasAllReadRequested: true, hasAllWriteRequested: true }, + }); jest .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: '/slos', search: '', state: '', hash: '' }); @@ -175,6 +179,7 @@ describe('SLOs Page', () => { data: {}, }); }); + it('navigates to the SLOs Welcome Page', async () => { await act(async () => { render(); @@ -207,9 +212,28 @@ describe('SLOs Page', () => { }); }); - it('should have a create new SLO button', async () => { + it('navigates to the SLOs Welcome Page when the user has not the request read permissions', async () => { useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); + useFetchHistoricalSummaryMock.mockReturnValue({ + isLoading: false, + data: historicalSummaryData, + }); + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { hasAllReadRequested: false, hasAllWriteRequested: false }, + }); + await act(async () => { + render(); + }); + + await waitFor(() => { + expect(mockNavigate).toBeCalledWith(paths.slosWelcome); + }); + }); + + it('should have a create new SLO button', async () => { + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, data: historicalSummaryData, diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/slos.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/slos.tsx index fdb40e12ba4e2..30d519e61e38f 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/slos.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/slos.tsx @@ -15,6 +15,7 @@ import { HeaderMenu } from '../../components/header_menu/header_menu'; import { SloOutdatedCallout } from '../../components/slo/slo_outdated_callout'; import { useFetchSloList } from '../../hooks/use_fetch_slo_list'; import { useLicense } from '../../hooks/use_license'; +import { usePermissions } from '../../hooks/use_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { useKibana } from '../../utils/kibana_react'; import { CreateSloBtn } from './components/common/create_slo_btn'; @@ -31,14 +32,9 @@ export function SlosPage() { } = useKibana().services; const { ObservabilityPageTemplate } = usePluginContext(); const { hasAtLeast } = useLicense(); + const { data: permissions } = usePermissions(); - const { - isLoading, - isError, - data: sloList, - } = useFetchSloList({ - perPage: 0, - }); + const { isLoading, isError, data: sloList } = useFetchSloList({ perPage: 0 }); const { total } = sloList ?? { total: 0 }; useBreadcrumbs([ @@ -55,7 +51,11 @@ export function SlosPage() { if ((!isLoading && total === 0) || hasAtLeast('platinum') === false || isError) { navigateToUrl(basePath.prepend(paths.slosWelcome)); } - }, [basePath, hasAtLeast, isError, isLoading, navigateToUrl, total]); + + if (permissions?.hasAllReadRequested === false) { + navigateToUrl(basePath.prepend(paths.slosWelcome)); + } + }, [basePath, hasAtLeast, isError, isLoading, navigateToUrl, total, permissions]); return ( Portal node
); @@ -38,8 +36,7 @@ HeaderMenuPortalMock.mockReturnValue(
Portal node
); const useKibanaMock = useKibana as jest.Mock; const useLicenseMock = useLicense as jest.Mock; const useFetchSloListMock = useFetchSloList as jest.Mock; -const useCapabilitiesMock = useCapabilities as jest.Mock; -const useGlobalDiagnosisMock = useFetchSloGlobalDiagnosis as jest.Mock; +const usePermissionsMock = usePermissions as jest.Mock; const mockNavigate = jest.fn(); @@ -64,7 +61,6 @@ describe('SLOs Welcome Page', () => { beforeEach(() => { jest.clearAllMocks(); mockKibana(); - useCapabilitiesMock.mockReturnValue({ hasWriteCapabilities: true, hasReadCapabilities: true }); jest .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: '/slos/welcome', search: '', state: '', hash: '' }); @@ -74,9 +70,11 @@ describe('SLOs Welcome Page', () => { it('renders the welcome message with subscription buttons', async () => { useFetchSloListMock.mockReturnValue({ isLoading: false, data: emptySloList }); useLicenseMock.mockReturnValue({ hasAtLeast: () => false }); - useGlobalDiagnosisMock.mockReturnValue({ + usePermissionsMock.mockReturnValue({ + isLoading: false, data: { - userPrivileges: { write: { has_all_requested: true }, read: { has_all_requested: true } }, + hasAllWriteRequested: true, + hasAllReadRequested: true, }, }); @@ -91,8 +89,12 @@ describe('SLOs Welcome Page', () => { describe('when the correct license is found', () => { beforeEach(() => { useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); - useGlobalDiagnosisMock.mockReturnValue({ - isError: false, + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { + hasAllWriteRequested: true, + hasAllReadRequested: true, + }, }); }); @@ -102,9 +104,12 @@ describe('SLOs Welcome Page', () => { }); it('disables the create slo button when no write capabilities', async () => { - useCapabilitiesMock.mockReturnValue({ - hasWriteCapabilities: false, - hasReadCapabilities: true, + usePermissionsMock.mockReturnValue({ + isLoading: false, + data: { + hasAllWriteRequested: false, + hasAllReadRequested: true, + }, }); render(); @@ -117,16 +122,11 @@ describe('SLOs Welcome Page', () => { }); it('disables the create slo button when no cluster permissions capabilities', async () => { - useCapabilitiesMock.mockReturnValue({ - hasWriteCapabilities: true, - hasReadCapabilities: true, - }); - useGlobalDiagnosisMock.mockReturnValue({ + usePermissionsMock.mockReturnValue({ + isLoading: false, data: { - userPrivileges: { - write: { has_all_requested: false }, - read: { has_all_requested: true }, - }, + hasAllWriteRequested: false, + hasAllReadRequested: true, }, }); @@ -138,12 +138,11 @@ describe('SLOs Welcome Page', () => { }); it('should display the welcome message with a Create new SLO button which should navigate to the SLO Creation page', async () => { - useGlobalDiagnosisMock.mockReturnValue({ + usePermissionsMock.mockReturnValue({ + isLoading: false, data: { - userPrivileges: { - write: { has_all_requested: true }, - read: { has_all_requested: true }, - }, + hasAllWriteRequested: true, + hasAllReadRequested: true, }, }); @@ -163,12 +162,11 @@ describe('SLOs Welcome Page', () => { describe('when loading is done and results are found', () => { beforeEach(() => { useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); - useGlobalDiagnosisMock.mockReturnValue({ + usePermissionsMock.mockReturnValue({ + isLoading: false, data: { - userPrivileges: { - write: { has_all_requested: true }, - read: { has_all_requested: true }, - }, + hasAllWriteRequested: true, + hasAllReadRequested: true, }, }); }); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos_welcome/slos_welcome.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos_welcome/slos_welcome.tsx index 53b08809ecc6a..fc03009beb72e 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos_welcome/slos_welcome.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos_welcome/slos_welcome.tsx @@ -5,65 +5,61 @@ * 2.0. */ -import React, { useEffect } from 'react'; import { - EuiPageTemplate, EuiButton, - EuiTitle, - EuiLink, - EuiImage, - EuiSpacer, EuiFlexGroup, EuiFlexItem, + EuiImage, + EuiLink, + EuiPageTemplate, + EuiSpacer, + EuiTitle, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; - -import { useKibana } from '../../utils/kibana_react'; +import React, { useEffect } from 'react'; +import { paths } from '../../../common/locators/paths'; +import { HeaderMenu } from '../../components/header_menu/header_menu'; +import { SloOutdatedCallout } from '../../components/slo/slo_outdated_callout'; +import { SloPermissionsCallout } from '../../components/slo/slo_permissions_callout'; +import { useFetchSloList } from '../../hooks/use_fetch_slo_list'; import { useLicense } from '../../hooks/use_license'; +import { usePermissions } from '../../hooks/use_permissions'; import { usePluginContext } from '../../hooks/use_plugin_context'; -import { useCapabilities } from '../../hooks/use_capabilities'; -import { useFetchSloList } from '../../hooks/use_fetch_slo_list'; -import { paths } from '../../../common/locators/paths'; +import { useKibana } from '../../utils/kibana_react'; import illustration from './assets/illustration.svg'; -import { useFetchSloGlobalDiagnosis } from '../../hooks/use_fetch_global_diagnosis'; -import { SloOutdatedCallout } from '../../components/slo/slo_outdated_callout'; -import { HeaderMenu } from '../../components/header_menu/header_menu'; export function SlosWelcomePage() { const { application: { navigateToUrl }, http: { basePath }, } = useKibana().services; - const { hasWriteCapabilities } = useCapabilities(); - const { data: globalDiagnosis } = useFetchSloGlobalDiagnosis(); - const { ObservabilityPageTemplate } = usePluginContext(); + const { ObservabilityPageTemplate } = usePluginContext(); + const { data: permissions } = usePermissions(); const { hasAtLeast } = useLicense(); const hasRightLicense = hasAtLeast('platinum'); - const { isLoading, data: sloList } = useFetchSloList(); + const { data: sloList } = useFetchSloList(); const { total } = sloList ?? { total: 0 }; - const hasRequiredWritePrivileges = !!globalDiagnosis?.userPrivileges.write.has_all_requested; - const hasRequiredReadPrivileges = !!globalDiagnosis?.userPrivileges.read.has_all_requested; + const hasSlosAndPermissions = + total > 0 && hasRightLicense && permissions?.hasAllReadRequested === true; const handleClickCreateSlo = () => { navigateToUrl(basePath.prepend(paths.sloCreate)); }; - const hasSlosAndHasPermissions = - total > 0 && hasAtLeast('platinum') === true && hasRequiredReadPrivileges; - useEffect(() => { - if (hasSlosAndHasPermissions) { + if (hasSlosAndPermissions) { navigateToUrl(basePath.prepend(paths.slos)); } - }, [basePath, hasSlosAndHasPermissions, navigateToUrl]); + }, [basePath, navigateToUrl, hasSlosAndPermissions]); - return hasSlosAndHasPermissions || isLoading ? null : ( + return ( + @@ -117,7 +113,7 @@ export function SlosWelcomePage() { fill color="primary" onClick={handleClickCreateSlo} - disabled={!hasWriteCapabilities || !hasRequiredWritePrivileges} + disabled={!permissions?.hasAllWriteRequested} > {i18n.translate('xpack.slo.sloList.welcomePrompt.buttonLabel', { defaultMessage: 'Create SLO', diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index 697d3ceb560df..38c183316a591 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -14,7 +14,7 @@ export async function getGlobalDiagnosis( ) { const licenseInfo = licensing.license.toJSON(); const userWritePrivileges = await esClient.security.hasPrivileges({ - cluster: ['manage_transform'], + cluster: ['manage_transform', 'manage_ingest_pipelines'], index: [{ names: '.slo-*', privileges: ['all'] }], }); const userReadPrivileges = await esClient.security.hasPrivileges({ From 172163352761eb6edf870df79cdd0adf9c292123 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 18 Jun 2024 10:10:43 -0700 Subject: [PATCH 066/127] [HTTP/OAS] Add tags and descriptions for uptime setting APIs (#184268) --- .../server/legacy_uptime/routes/uptime_route_wrapper.ts | 6 +++++- .../uptime/server/legacy_uptime/uptime_server.ts | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/uptime_route_wrapper.ts b/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/uptime_route_wrapper.ts index 5beaa563790e8..2590db8524105 100644 --- a/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/uptime_route_wrapper.ts +++ b/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/routes/uptime_route_wrapper.ts @@ -12,7 +12,11 @@ import { UptimeEsClient } from '../lib/lib'; export const uptimeRouteWrapper: UMKibanaRouteWrapper = (uptimeRoute, server) => ({ ...uptimeRoute, options: { - tags: ['access:uptime-read', ...(uptimeRoute?.writeAccess ? ['access:uptime-write'] : [])], + tags: [ + 'oas-tag:uptime', + 'access:uptime-read', + ...(uptimeRoute?.writeAccess ? ['access:uptime-write'] : []), + ], }, handler: async (context, request, response) => { const coreContext = await context.core; diff --git a/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/uptime_server.ts b/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/uptime_server.ts index 0c417a6e061e6..b8a9b56c2a909 100644 --- a/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/uptime_server.ts +++ b/x-pack/plugins/observability_solution/uptime/server/legacy_uptime/uptime_server.ts @@ -89,6 +89,7 @@ export const initUptimeServer = ( router.versioned .get({ access: 'public', + description: `Get uptime settings`, path: routeDefinition.path, options: { tags: options?.tags, @@ -115,6 +116,7 @@ export const initUptimeServer = ( router.versioned .put({ access: 'public', + description: `Update uptime settings`, path: routeDefinition.path, options: { tags: options?.tags, From 7ee93179e3c0574c86957bbc06e47b69b797fb75 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 18 Jun 2024 13:15:04 -0400 Subject: [PATCH 067/127] [Fleet] Add global data tags telemetry (#186390) --- .../fleet/server/collectors/agent_policies.ts | 20 +++++++++++++++++++ .../fleet_usage_telemetry.test.ts | 10 ++++++++++ .../services/telemetry/fleet_usages_schema.ts | 13 ++++++++++++ 3 files changed, 43 insertions(+) diff --git a/x-pack/plugins/fleet/server/collectors/agent_policies.ts b/x-pack/plugins/fleet/server/collectors/agent_policies.ts index d70524e5f1e32..5210e7f3b229d 100644 --- a/x-pack/plugins/fleet/server/collectors/agent_policies.ts +++ b/x-pack/plugins/fleet/server/collectors/agent_policies.ts @@ -18,6 +18,8 @@ import type { OutputSOAttributes, AgentPolicy } from '../types'; export interface AgentPoliciesUsage { count: number; output_types: string[]; + count_with_global_data_tags: number; + avg_number_global_data_tags_per_policy?: number; } export const getAgentPoliciesUsage = async ( @@ -52,8 +54,26 @@ export const getAgentPoliciesUsage = async ( }) ); + const [policiesWithGlobalDataTag, totalNumberOfGlobalDataTagFields] = agentPolicies.reduce( + ([policiesNumber, fieldsNumber], agentPolicy) => { + if (agentPolicy.attributes.global_data_tags?.length ?? 0 > 0) { + return [ + policiesNumber + 1, + fieldsNumber + (agentPolicy.attributes.global_data_tags?.length ?? 0), + ]; + } + return [policiesNumber, fieldsNumber]; + }, + [0, 0] + ); + return { count: totalAgentPolicies, output_types: Array.from(uniqueOutputTypes), + count_with_global_data_tags: policiesWithGlobalDataTag, + avg_number_global_data_tags_per_policy: + policiesWithGlobalDataTag > 0 + ? Math.round(totalNumberOfGlobalDataTagFields / policiesWithGlobalDataTag) + : undefined, }; }; diff --git a/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts b/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts index 3ee659793f53f..77b3278bad39a 100644 --- a/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts @@ -428,6 +428,10 @@ describe('fleet usage telemetry', () => { schema_version: '1.0.0', data_output_id: 'output2', monitoring_output_id: 'output3', + global_data_tags: [ + { name: 'test', value: 'test1' }, + { name: 'test2', value: 'test2' }, + ], }, { id: 'policy2' } ); @@ -446,6 +450,10 @@ describe('fleet usage telemetry', () => { schema_version: '1.0.0', data_output_id: 'output4', monitoring_output_id: 'output4', + global_data_tags: [ + { name: 'test', value: 'test1' }, + { name: 'test2', value: 'test2' }, + ], }, { id: 'policy3' } ); @@ -566,6 +574,8 @@ describe('fleet usage telemetry', () => { agent_policies: { count: 3, output_types: expect.arrayContaining(['elasticsearch', 'logstash', 'third_type']), + count_with_global_data_tags: 2, + avg_number_global_data_tags_per_policy: 2, }, agent_logs_panics_last_hour: [ { diff --git a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts index 35138145a7141..1720470b65ad8 100644 --- a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts +++ b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts @@ -346,6 +346,19 @@ export const fleetUsagesSchema: RootSchema = { _meta: { description: 'Output types of agent policies' }, }, }, + count_with_global_data_tags: { + type: 'long', + _meta: { + description: 'Number of agent policies using global data tags', + }, + }, + avg_number_global_data_tags_per_policy: { + type: 'long', + _meta: { + description: + 'Average number of global data tags defined per agent policy (accross policies using global data tags)', + }, + }, }, }, agent_checkin_status: { From 3528d54e2749f964c0eca6b561098ca370d40a78 Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 18 Jun 2024 12:17:33 -0500 Subject: [PATCH 068/127] [ci] Remove 8.13 (#186377) 8.14 is released. 8.13 tests do not need to run now. --- .../pipeline-resource-definitions/kibana-on-merge.yml | 2 +- versions.json | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.buildkite/pipeline-resource-definitions/kibana-on-merge.yml b/.buildkite/pipeline-resource-definitions/kibana-on-merge.yml index 8952951a27a5b..497968f39ad95 100644 --- a/.buildkite/pipeline-resource-definitions/kibana-on-merge.yml +++ b/.buildkite/pipeline-resource-definitions/kibana-on-merge.yml @@ -25,7 +25,7 @@ spec: REPORT_FAILED_TESTS_TO_GITHUB: 'true' ELASTIC_SLACK_NOTIFICATIONS_ENABLED: 'true' allow_rebuilds: true - branch_configuration: main 7.17 8.13 8.14 + branch_configuration: main 7.17 8.14 default_branch: main repository: elastic/kibana pipeline_file: .buildkite/pipelines/on_merge.yml diff --git a/versions.json b/versions.json index 9240760ec44f4..f43e07cfdf2e2 100644 --- a/versions.json +++ b/versions.json @@ -13,12 +13,6 @@ "currentMajor": true, "previousMinor": true }, - { - "version": "8.13.5", - "branch": "8.13", - "currentMajor": true, - "previousMinor": true - }, { "version": "7.17.23", "branch": "7.17", From 243ed27d1a7ebee50677210632293dd07fe80172 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Tue, 18 Jun 2024 19:23:16 +0200 Subject: [PATCH 069/127] Remove IE check + banner (#186396) ## Summary Address https://github.com/elastic/kibana/issues/138089 --- .../src/chrome_service.tsx | 30 ------------------- .../translations/translations/fr-FR.json | 2 -- .../translations/translations/ja-JP.json | 2 -- .../translations/translations/zh-CN.json | 2 -- 4 files changed, 36 deletions(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx index 15ccb7c6a5531..d2922b9a96611 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.tsx @@ -11,7 +11,6 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { BehaviorSubject, combineLatest, merge, type Observable, of, ReplaySubject } from 'rxjs'; import { mergeMap, map, takeUntil, filter } from 'rxjs'; import { parse } from 'url'; -import { EuiLink } from '@elastic/eui'; import useObservable from 'react-use/lib/useObservable'; import type { CoreContext } from '@kbn/core-base-browser-internal'; @@ -314,14 +313,6 @@ export class ChromeService { projectNavigation.setProjectName(projectName); }; - const isIE = () => { - const ua = window.navigator.userAgent; - const msie = ua.indexOf('MSIE '); // IE 10 or older - const trident = ua.indexOf('Trident/'); // IE 11 - - return msie > 0 || trident > 0; - }; - if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { notifications.toasts.addWarning({ title: mountReactNode( @@ -333,27 +324,6 @@ export class ChromeService { }); } - if (isIE()) { - notifications.toasts.addWarning({ - title: mountReactNode( - - -
- ), - }} - /> - ), - }); - } - const getHeaderComponent = () => { const defaultChromeStyle = chromeStyleSubject$.getValue(); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 7305a2ca70a1d..cf8a0222a0378 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -547,7 +547,6 @@ "controls.timeSlider.previousLabel": "Fenêtre temporelle précédente", "controls.timeSlider.settings.pinStart": "Épingler le début", "controls.timeSlider.settings.unpinStart": "Désépingler le début", - "core.chrome.browserDeprecationWarning": "La prise en charge d'Internet Explorer sera abandonnée dans les futures versions de ce logiciel. Veuillez consulter le site {link}.", "core.deprecations.deprecations.fetchFailedMessage": "Impossible d'extraire les informations de déclassement pour le plug-in {domainId}.", "core.deprecations.deprecations.fetchFailedTitle": "Impossible d'extraire les déclassements pour {domainId}", "core.deprecations.elasticsearchSSL.manualSteps1": "Ajoutez le paramètre \"{missingSetting}\" à kibana.yml.", @@ -678,7 +677,6 @@ "core.application.appNotFound.pageDescription": "Aucune application détectée pour cette URL. Revenez en arrière ou sélectionnez une application dans le menu.", "core.application.appNotFound.title": "Application introuvable", "core.application.appRenderError.defaultTitle": "Erreur d'application", - "core.chrome.browserDeprecationLink": "la matrice de prise en charge sur notre site web", "core.chrome.legacyBrowserWarning": "Votre navigateur ne satisfait pas aux exigences de sécurité de Kibana.", "core.deprecations.deprecations.fetchFailed.manualStepOneMessage": "Vérifiez le message d'erreur dans les logs de serveur Kibana.", "core.deprecations.elasticsearchUsername.manualSteps1": "Utilisez l'outil CLI elasticsearch-service-tokens afin de créer un jeton pour le compte de service \"elastic/kibana\".", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 2c6f6ea67b15e..c50d9b9b36b2f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -549,7 +549,6 @@ "controls.timeSlider.previousLabel": "前の時間ウィンドウ", "controls.timeSlider.settings.pinStart": "開始をピン留め", "controls.timeSlider.settings.unpinStart": "開始をピン留め解除", - "core.chrome.browserDeprecationWarning": "このソフトウェアの将来のバージョンでは、Internet Explorerのサポートが削除されます。{link}をご確認ください。", "core.deprecations.deprecations.fetchFailedMessage": "プラグイン{domainId}の廃止予定情報を取得できません。", "core.deprecations.deprecations.fetchFailedTitle": "{domainId}の廃止予定を取得できませんでした", "core.deprecations.elasticsearchSSL.manualSteps1": "\"{missingSetting}\"設定をkibana.ymlに追加します。", @@ -678,7 +677,6 @@ "core.application.appNotFound.pageDescription": "この URL にアプリケーションが見つかりませんでした。前の画面に戻るか、メニューからアプリを選択してみてください。", "core.application.appNotFound.title": "アプリケーションが見つかりません", "core.application.appRenderError.defaultTitle": "アプリケーションエラー", - "core.chrome.browserDeprecationLink": "Web サイトのサポートマトリックス", "core.chrome.legacyBrowserWarning": "ご使用のブラウザが Kibana のセキュリティ要件を満たしていません。", "core.deprecations.deprecations.fetchFailed.manualStepOneMessage": "エラーメッセージについては、Kibanaサーバーログを確認してください。", "core.deprecations.elasticsearchUsername.manualSteps1": "elasticsearch-service-tokens CLIツールを使用して、「elastic/kibana」サービスアカウントの新しいサービスアカウントトークンを作成します。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 66f2bb582b4be..cbfe1c3c90544 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -549,7 +549,6 @@ "controls.timeSlider.previousLabel": "上一时间窗口", "controls.timeSlider.settings.pinStart": "固定开始屏幕", "controls.timeSlider.settings.unpinStart": "取消固定开始屏幕", - "core.chrome.browserDeprecationWarning": "本软件的未来版本将放弃对 Internet Explorer 的支持,请查看{link}。", "core.deprecations.deprecations.fetchFailedMessage": "无法提取插件 {domainId} 的弃用信息。", "core.deprecations.deprecations.fetchFailedTitle": "无法提取 {domainId} 的弃用信息", "core.deprecations.elasticsearchSSL.manualSteps1": "将“{missingSetting}”设置添加到 kibana.yml。", @@ -680,7 +679,6 @@ "core.application.appNotFound.pageDescription": "在此 URL 未找到任何应用程序。尝试返回或从菜单中选择应用。", "core.application.appNotFound.title": "未找到应用程序", "core.application.appRenderError.defaultTitle": "应用程序错误", - "core.chrome.browserDeprecationLink": "我们网站上的支持矩阵", "core.chrome.legacyBrowserWarning": "您的浏览器不满足 Kibana 的安全要求。", "core.deprecations.deprecations.fetchFailed.manualStepOneMessage": "请在 Kibana 服务器日志中查看错误消息。", "core.deprecations.elasticsearchUsername.manualSteps1": "使用 elasticsearch-service-tokens CLI 工具为“elastic/kibana”服务帐户创建新的服务帐户令牌。", From dde8ef93bb793d973522a67e67997fe09606cd51 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 18 Jun 2024 10:25:34 -0700 Subject: [PATCH 070/127] [OAS] Edits OpenAPI documents for machine learning sync API (#186318) --- x-pack/plugins/ml/common/openapi/ml_apis.yaml | 23 ++++++++++--------- .../ml/common/openapi/ml_apis_serverless.yaml | 19 ++++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/ml/common/openapi/ml_apis.yaml b/x-pack/plugins/ml/common/openapi/ml_apis.yaml index 9f2a7de498184..d2854d049098e 100644 --- a/x-pack/plugins/ml/common/openapi/ml_apis.yaml +++ b/x-pack/plugins/ml/common/openapi/ml_apis.yaml @@ -1,8 +1,8 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Machine learning APIs description: Kibana APIs for the machine learning feature - version: "1.0.2" + version: "1.0.1" license: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license @@ -14,8 +14,11 @@ servers: paths: /api/ml/saved_objects/sync: get: - summary: Synchronizes Kibana saved objects for machine learning jobs and trained models. - description: This API runs automatically when you start Kibana and periodically thereafter. + summary: Sync saved objects in the default space + description: > + Synchronizes Kibana saved objects for machine learning jobs and trained models in the default space. + You must have `all` privileges for the **Machine Learning** feature in the **Analytics** section of the Kibana feature privileges. + This API runs automatically when you start Kibana and periodically thereafter. operationId: mlSync tags: - ml @@ -40,8 +43,9 @@ paths: /s/{spaceId}/api/ml/saved_objects/sync: get: - summary: Synchronizes Kibana saved objects for machine learning jobs and trained models. + summary: Sync saved objects description: > + Synchronizes Kibana saved objects for machine learning jobs and trained models. You must have `all` privileges for the **Machine Learning** feature in the **Analytics** section of the Kibana feature privileges. This API runs automatically when you start Kibana and periodically thereafter. operationId: mlSyncWithSpaceId @@ -82,8 +86,7 @@ components: required: false schema: type: boolean - examples: - - true + example: 'true' securitySchemes: basicAuth: type: http @@ -188,14 +191,12 @@ components: properties: error: type: string - examples: - - Unauthorized + example: Unauthorized message: type: string statusCode: type: integer - examples: - - 401 + example: 401 examples: mlSyncExample: summary: Two anomaly detection jobs required synchronization in this example. diff --git a/x-pack/plugins/ml/common/openapi/ml_apis_serverless.yaml b/x-pack/plugins/ml/common/openapi/ml_apis_serverless.yaml index 6ff44e29517e6..d09b78c1155ae 100644 --- a/x-pack/plugins/ml/common/openapi/ml_apis_serverless.yaml +++ b/x-pack/plugins/ml/common/openapi/ml_apis_serverless.yaml @@ -1,8 +1,8 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Machine learning APIs description: Kibana APIs for the machine learning feature - version: "1.0.2" + version: "1.0.1" license: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license @@ -14,8 +14,10 @@ servers: paths: /api/ml/saved_objects/sync: get: - summary: Synchronizes Kibana saved objects for machine learning jobs and trained models. - description: This API runs automatically when you start Kibana and periodically thereafter. + summary: Sync machine learning saved objects + description: > + Synchronizes Kibana saved objects for machine learning jobs and trained models. + This API runs automatically when you start Kibana and periodically thereafter. operationId: mlSync tags: - ml @@ -46,8 +48,7 @@ components: required: false schema: type: boolean - examples: - - true + example: 'true' securitySchemes: apiKeyAuth: type: apiKey @@ -149,14 +150,12 @@ components: properties: error: type: string - examples: - - Unauthorized + example: Unauthorized message: type: string statusCode: type: integer - examples: - - 401 + example: 401 examples: mlSyncExample: summary: Two anomaly detection jobs required synchronization in this example. From e2a98cf965f61a5a2e23787869b214a5ba9061a5 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Tue, 18 Jun 2024 19:25:51 +0200 Subject: [PATCH 071/127] Add dashboard metadata to the info flyout (#185941) ## Summary Close https://github.com/elastic/kibana-team/issues/898 - Show createdAt, createdBy, updatedAt, updatedBy in info flyout. Add a bit of special handling for managed objects and when info is not available. - I had to extract some components into a separate package to use them in contentEditor package - tiny tweaks to column width and "no creator" state ![Screenshot 2024-06-12 at 17 01 45](https://github.com/elastic/kibana/assets/7784120/b2093c03-67a0-49a5-8a45-93d9e57813ca) **Unknown creator:** ![Screenshot 2024-06-12 at 17 01 53](https://github.com/elastic/kibana/assets/7784120/3e520f6a-9a19-455f-b564-571c3ad81b16) **For managed objects:** ![Screenshot 2024-06-12 at 17 01 57](https://github.com/elastic/kibana/assets/7784120/36ce1465-09a4-4936-a9f1-ca5794d45a7a) **Just created, no updates yet** ![Screenshot 2024-06-12 at 17 02 18](https://github.com/elastic/kibana/assets/7784120/1431210e-ce83-4409-ab99-6184b6f87d3a) --- .github/CODEOWNERS | 1 + package.json | 1 + .../src/components/activity_view.test.tsx | 113 +++++++++++ .../src/components/activity_view.tsx | 185 ++++++++++++++++++ .../src/components/editor_flyout_content.tsx | 7 +- .../editor_flyout_content_container.tsx | 1 + .../inspector_flyout_content.test.tsx | 17 ++ .../src/components/metadata_form.tsx | 16 +- .../src/open_content_editor.tsx | 8 +- .../content_editor/src/services.tsx | 16 +- .../content_editor/src/types.ts | 7 + .../content_editor/tsconfig.json | 8 +- .../table_list_view_common/index.ts | 2 + .../src/__jest__/created_by_filter.test.tsx | 2 +- .../src/__jest__/tests.helpers.tsx | 26 ++- .../src/components/user_filter_panel.tsx | 26 +-- .../src/components/user_missing_tip.tsx | 28 --- .../table_list_view_table/src/mocks.tsx | 2 - .../table_list_view_table/src/services.tsx | 76 +++---- .../src/table_list_view_table.tsx | 25 ++- .../table_list_view_table/tsconfig.json | 3 +- .../user_profiles/README.md | 3 + .../content-management/user_profiles/index.ts | 19 ++ .../user_profiles/jest.config.js | 13 ++ .../user_profiles/kibana.jsonc | 5 + .../user_profiles/package.json | 6 + .../user_profiles/src/components/index.ts | 11 ++ .../src/components/managed_avatar_tip.tsx | 12 +- .../src/components/user_avatar_tip.tsx | 12 +- .../src/components/user_missing_tip.tsx | 53 +++++ .../user_profiles/src/queries.ts | 36 ++++ .../user_profiles/src/services.tsx | 82 ++++++++ .../src/utils/batcher.test.tsx | 0 .../src/utils/batcher.ts | 0 .../user_profiles/tsconfig.json | 24 +++ .../use_dashboard_listing_table.test.tsx | 1 + .../hooks/use_dashboard_listing_table.tsx | 3 + tsconfig.base.json | 2 + yarn.lock | 4 + 39 files changed, 715 insertions(+), 141 deletions(-) create mode 100644 packages/content-management/content_editor/src/components/activity_view.test.tsx create mode 100644 packages/content-management/content_editor/src/components/activity_view.tsx delete mode 100644 packages/content-management/table_list_view_table/src/components/user_missing_tip.tsx create mode 100644 packages/content-management/user_profiles/README.md create mode 100644 packages/content-management/user_profiles/index.ts create mode 100644 packages/content-management/user_profiles/jest.config.js create mode 100644 packages/content-management/user_profiles/kibana.jsonc create mode 100644 packages/content-management/user_profiles/package.json create mode 100644 packages/content-management/user_profiles/src/components/index.ts rename packages/content-management/{table_list_view_table => user_profiles}/src/components/managed_avatar_tip.tsx (70%) rename packages/content-management/{table_list_view_table => user_profiles}/src/components/user_avatar_tip.tsx (72%) create mode 100644 packages/content-management/user_profiles/src/components/user_missing_tip.tsx create mode 100644 packages/content-management/user_profiles/src/queries.ts create mode 100644 packages/content-management/user_profiles/src/services.tsx rename packages/content-management/{table_list_view_table => user_profiles}/src/utils/batcher.test.tsx (100%) rename packages/content-management/{table_list_view_table => user_profiles}/src/utils/batcher.ts (100%) create mode 100644 packages/content-management/user_profiles/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a5fc58216acbf..e519143df765d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -101,6 +101,7 @@ packages/content-management/tabbed_table_list_view @elastic/appex-sharedux packages/content-management/table_list_view @elastic/appex-sharedux packages/content-management/table_list_view_common @elastic/appex-sharedux packages/content-management/table_list_view_table @elastic/appex-sharedux +packages/content-management/user_profiles @elastic/appex-sharedux packages/kbn-content-management-utils @elastic/kibana-data-discovery examples/controls_example @elastic/kibana-presentation src/plugins/controls @elastic/kibana-presentation diff --git a/package.json b/package.json index 0c50f51a82f2e..989341509eb04 100644 --- a/package.json +++ b/package.json @@ -217,6 +217,7 @@ "@kbn/content-management-table-list-view": "link:packages/content-management/table_list_view", "@kbn/content-management-table-list-view-common": "link:packages/content-management/table_list_view_common", "@kbn/content-management-table-list-view-table": "link:packages/content-management/table_list_view_table", + "@kbn/content-management-user-profiles": "link:packages/content-management/user_profiles", "@kbn/content-management-utils": "link:packages/kbn-content-management-utils", "@kbn/controls-example-plugin": "link:examples/controls_example", "@kbn/controls-plugin": "link:src/plugins/controls", diff --git a/packages/content-management/content_editor/src/components/activity_view.test.tsx b/packages/content-management/content_editor/src/components/activity_view.test.tsx new file mode 100644 index 0000000000000..252591aba72ac --- /dev/null +++ b/packages/content-management/content_editor/src/components/activity_view.test.tsx @@ -0,0 +1,113 @@ +/* + * Copyright 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 { render, screen, waitFor } from '@testing-library/react'; +import { UserProfilesProvider } from '@kbn/content-management-user-profiles'; +import { I18nProvider } from '@kbn/i18n-react'; + +import { ActivityView as ActivityViewComponent, ActivityViewProps } from './activity_view'; + +const mockGetUserProfile = jest.fn(async (uid: string) => ({ + uid, + enabled: true, + data: {}, + user: { username: uid, full_name: uid.toLocaleUpperCase() }, +})); + +const ActivityView = (props: ActivityViewProps) => { + return ( + + + + + + ); +}; + +test('should render activity view', () => { + render(); + + expect(screen.getByTestId('activityView')).toBeVisible(); + + expect(screen.getByTestId('createdByCard')).toHaveTextContent(/Unknown/); + expect(() => screen.getByTestId('updateByCard')).toThrow(); +}); + +test('should render creator card', async () => { + render(); + + await waitFor(() => { + const createdByCard = screen.getByTestId('createdByCard'); + expect(createdByCard).toHaveTextContent(/JOHN/); + expect(createdByCard).toHaveTextContent(/June 13/); + }); +}); + +test('should not render updater card when updatedAt matches createdAt', async () => { + render( + + ); + + expect(screen.getByTestId('createdByCard')).toBeVisible(); + expect(() => screen.getByTestId('updateByCard')).toThrow(); +}); + +test('should render updater card', async () => { + render( + + ); + + await waitFor(() => { + const createdByCard = screen.getByTestId('createdByCard'); + expect(createdByCard).toHaveTextContent(/JOHN/); + expect(createdByCard).toHaveTextContent(/June 13/); + }); + + await waitFor(() => { + const updatedByCard = screen.getByTestId('updatedByCard'); + expect(updatedByCard).toHaveTextContent(/PETE/); + expect(updatedByCard).toHaveTextContent(/June 14/); + }); +}); + +test('should handle managed objects', async () => { + render( + + ); + + await waitFor(() => { + const createdByCard = screen.getByTestId('createdByCard'); + expect(createdByCard).toHaveTextContent(/System/); + expect(createdByCard).toHaveTextContent(/June 13/); + }); + + const updatedByCard = screen.getByTestId('updatedByCard'); + expect(updatedByCard).toHaveTextContent(/System/); + expect(updatedByCard).toHaveTextContent(/June 14/); +}); diff --git a/packages/content-management/content_editor/src/components/activity_view.tsx b/packages/content-management/content_editor/src/components/activity_view.tsx new file mode 100644 index 0000000000000..eb413acb20e36 --- /dev/null +++ b/packages/content-management/content_editor/src/components/activity_view.tsx @@ -0,0 +1,185 @@ +/* + * Copyright 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 { + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiIconTip, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { + UserAvatarTip, + useUserProfile, + NoUpdaterTip, + NoCreatorTip, + ManagedAvatarTip, +} from '@kbn/content-management-user-profiles'; +import { getUserDisplayName } from '@kbn/user-profile-components'; + +import { Item } from '../types'; + +export interface ActivityViewProps { + item: Pick; +} + +export const ActivityView = ({ item }: ActivityViewProps) => { + const showLastUpdated = Boolean(item.updatedAt && item.updatedAt !== item.createdAt); + + const UnknownUserLabel = ( + + ); + + const ManagedUserLabel = ( + <> + {' '} + + + ); + + return ( + + {' '} + + } + /> + + } + fullWidth + data-test-subj={'activityView'} + > + <> + + + + ) : item.managed ? ( + <>{ManagedUserLabel} + ) : ( + <> + {UnknownUserLabel} + + + ) + } + when={item.createdAt} + data-test-subj={'createdByCard'} + /> + + + {showLastUpdated && ( + + ) : item.managed ? ( + <>{ManagedUserLabel} + ) : ( + <> + {UnknownUserLabel} + + + ) + } + when={item.updatedAt} + data-test-subj={'updatedByCard'} + /> + )} + + + + + ); +}; + +const dateFormatter = new Intl.DateTimeFormat(i18n.getLocale(), { + dateStyle: 'long', + timeStyle: 'short', +}); + +const ActivityCard = ({ + what, + when, + who, + 'data-test-subj': dataTestSubj, +}: { + what: string; + who: React.ReactNode; + when?: string; + 'data-test-subj'?: string; +}) => { + return ( + + + {what} + + + + {who} + + {when && ( + <> + + + + + + )} + + ); +}; + +const UserLabel = ({ uid }: { uid: string }) => { + const userQuery = useUserProfile(uid); + + if (!userQuery.data) return null; + + return ( + <> + {getUserDisplayName(userQuery.data.user)} + + ); +}; diff --git a/packages/content-management/content_editor/src/components/editor_flyout_content.tsx b/packages/content-management/content_editor/src/components/editor_flyout_content.tsx index 007cc58c4e5ad..a347dbb2c4d31 100644 --- a/packages/content-management/content_editor/src/components/editor_flyout_content.tsx +++ b/packages/content-management/content_editor/src/components/editor_flyout_content.tsx @@ -28,6 +28,7 @@ import type { Item } from '../types'; import { MetadataForm } from './metadata_form'; import { useMetadataForm } from './use_metadata_form'; import type { CustomValidators } from './use_metadata_form'; +import { ActivityView } from './activity_view'; const getI18nTexts = ({ entityName }: { entityName: string }) => ({ saveButtonLabel: i18n.translate('contentManagement.contentEditor.saveButtonLabel', { @@ -55,6 +56,7 @@ export interface Props { }) => Promise; customValidators?: CustomValidators; onCancel: () => void; + showActivityView?: boolean; } const capitalize = (str: string) => `${str.charAt(0).toLocaleUpperCase()}${str.substring(1)}`; @@ -68,6 +70,7 @@ export const ContentEditorFlyoutContent: FC = ({ onSave, onCancel, customValidators, + showActivityView, }) => { const { euiTheme } = useEuiTheme(); const [isSubmitting, setIsSubmitting] = useState(false); @@ -147,7 +150,9 @@ export const ContentEditorFlyoutContent: FC = ({ tagsReferences={item.tags} TagList={TagList} TagSelector={TagSelector} - /> + > + {showActivityView && } + diff --git a/packages/content-management/content_editor/src/components/editor_flyout_content_container.tsx b/packages/content-management/content_editor/src/components/editor_flyout_content_container.tsx index c1a36406980f9..18094bc04f084 100644 --- a/packages/content-management/content_editor/src/components/editor_flyout_content_container.tsx +++ b/packages/content-management/content_editor/src/components/editor_flyout_content_container.tsx @@ -21,6 +21,7 @@ type CommonProps = Pick< | 'onCancel' | 'entityName' | 'customValidators' + | 'showActivityView' >; export type Props = CommonProps; diff --git a/packages/content-management/content_editor/src/components/inspector_flyout_content.test.tsx b/packages/content-management/content_editor/src/components/inspector_flyout_content.test.tsx index e4668d022d00d..c543acedbae5b 100644 --- a/packages/content-management/content_editor/src/components/inspector_flyout_content.test.tsx +++ b/packages/content-management/content_editor/src/components/inspector_flyout_content.test.tsx @@ -262,5 +262,22 @@ describe('', () => { tags: ['id-3', 'id-4'], // New selection }); }); + + test('should render activity view', async () => { + await act(async () => { + testBed = await setup({ showActivityView: true }); + }); + const { find, component } = testBed!; + + expect(find('activityView').exists()).toBe(true); + expect(find('activityView.createdByCard').exists()).toBe(true); + expect(find('activityView.updatedByCard').exists()).toBe(false); + + testBed.setProps({ + item: { ...savedObjectItem, updatedAt: '2021-01-01T00:00:00Z' }, + }); + component.update(); + expect(find('activityView.updatedByCard').exists()).toBe(true); + }); }); }); diff --git a/packages/content-management/content_editor/src/components/metadata_form.tsx b/packages/content-management/content_editor/src/components/metadata_form.tsx index 26b433edcd161..c5db98dc2811b 100644 --- a/packages/content-management/content_editor/src/components/metadata_form.tsx +++ b/packages/content-management/content_editor/src/components/metadata_form.tsx @@ -6,20 +6,20 @@ * Side Public License, v 1. */ -import React from 'react'; import type { FC } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { + EuiFieldText, EuiForm, EuiFormRow, - EuiFieldText, - EuiTextArea, EuiSpacer, + EuiTextArea, EuiToolTip, } from '@elastic/eui'; import { ContentEditorFlyoutWarningsCallOut } from './editor_flyout_warnings'; -import type { MetadataFormState, Field } from './use_metadata_form'; +import type { Field, MetadataFormState } from './use_metadata_form'; import type { SavedObjectsReference, Services } from '../services'; interface Props { @@ -42,6 +42,7 @@ export const MetadataForm: FC = ({ TagSelector, isReadonly, readonlyReason, + children, }) => { const { title, @@ -137,6 +138,13 @@ export const MetadataForm: FC = ({ )} + + {children && ( + <> + + {children} + + )} ); }; diff --git a/packages/content-management/content_editor/src/open_content_editor.tsx b/packages/content-management/content_editor/src/open_content_editor.tsx index b9bace1b45994..89b73991ba5d6 100644 --- a/packages/content-management/content_editor/src/open_content_editor.tsx +++ b/packages/content-management/content_editor/src/open_content_editor.tsx @@ -15,7 +15,13 @@ import type { ContentEditorFlyoutContentContainerProps } from './components'; export type OpenContentEditorParams = Pick< ContentEditorFlyoutContentContainerProps, - 'item' | 'onSave' | 'isReadonly' | 'readonlyReason' | 'entityName' | 'customValidators' + | 'item' + | 'onSave' + | 'isReadonly' + | 'readonlyReason' + | 'entityName' + | 'customValidators' + | 'showActivityView' >; export function useOpenContentEditor() { diff --git a/packages/content-management/content_editor/src/services.tsx b/packages/content-management/content_editor/src/services.tsx index 6edf58e45c846..8a9938ff51561 100644 --- a/packages/content-management/content_editor/src/services.tsx +++ b/packages/content-management/content_editor/src/services.tsx @@ -8,6 +8,10 @@ import type { FC, PropsWithChildren, ReactNode } from 'react'; import React, { useCallback, useContext, useMemo } from 'react'; +import { + UserProfilesProvider, + useUserProfilesServices, +} from '@kbn/content-management-user-profiles'; import type { EuiComboBoxProps } from '@elastic/eui'; import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser'; @@ -130,11 +134,19 @@ export const ContentEditorKibanaProvider: FC< return Comp; }, [savedObjectsTagging?.ui.components.TagList]); + const userProfilesServices = useUserProfilesServices(); + const openFlyout = useCallback( (node: ReactNode, options: OverlayFlyoutOpenOptions) => { - return coreOpenFlyout(toMountPoint(node, startServices), options); + return coreOpenFlyout( + toMountPoint( + {node}, + startServices + ), + options + ); }, - [coreOpenFlyout, startServices] + [coreOpenFlyout, startServices, userProfilesServices] ); return ( diff --git a/packages/content-management/content_editor/src/types.ts b/packages/content-management/content_editor/src/types.ts index 02607aa70d8bb..f54ad6b562ad8 100644 --- a/packages/content-management/content_editor/src/types.ts +++ b/packages/content-management/content_editor/src/types.ts @@ -13,4 +13,11 @@ export interface Item { title: string; description?: string; tags: SavedObjectsReference[]; + + createdAt?: string; + createdBy?: string; + updatedAt?: string; + updatedBy?: string; + + managed?: boolean; } diff --git a/packages/content-management/content_editor/tsconfig.json b/packages/content-management/content_editor/tsconfig.json index 8a7a1c08ba74a..b4f77e22f1f44 100644 --- a/packages/content-management/content_editor/tsconfig.json +++ b/packages/content-management/content_editor/tsconfig.json @@ -10,7 +10,9 @@ "react", "@kbn/ambient-ui-types", "@kbn/ambient-storybook-types", - "@emotion/react/types/css-prop" + "@emotion/react/types/css-prop", + "@testing-library/jest-dom", + "@testing-library/react" ] }, "include": [ @@ -26,7 +28,9 @@ "@kbn/core-i18n-browser", "@kbn/core-theme-browser", "@kbn/test-jest-helpers", - "@kbn/react-kibana-mount" + "@kbn/react-kibana-mount", + "@kbn/content-management-user-profiles", + "@kbn/user-profile-components" ], "exclude": [ "target/**/*" diff --git a/packages/content-management/table_list_view_common/index.ts b/packages/content-management/table_list_view_common/index.ts index fea9e6a918673..4ca206e196f17 100644 --- a/packages/content-management/table_list_view_common/index.ts +++ b/packages/content-management/table_list_view_common/index.ts @@ -11,6 +11,8 @@ import type { SavedObjectsReference } from '@kbn/content-management-content-edit export interface UserContentCommonSchema { id: string; updatedAt: string; + updatedBy?: string; + createdAt?: string; createdBy?: string; managed?: boolean; references: SavedObjectsReference[]; diff --git a/packages/content-management/table_list_view_table/src/__jest__/created_by_filter.test.tsx b/packages/content-management/table_list_view_table/src/__jest__/created_by_filter.test.tsx index 5593bda387778..bd68993b3f3ba 100644 --- a/packages/content-management/table_list_view_table/src/__jest__/created_by_filter.test.tsx +++ b/packages/content-management/table_list_view_table/src/__jest__/created_by_filter.test.tsx @@ -147,7 +147,7 @@ describe('created_by filter', () => { // wait until first render expect(await screen.findByTestId('itemsInMemTable')).toBeVisible(); - // 5 items in the list + // 4 items in the list expect(screen.getAllByTestId(/userContentListingTitleLink/)).toHaveLength(4); userEvent.click(screen.getByTestId('userFilterPopoverButton')); diff --git a/packages/content-management/table_list_view_table/src/__jest__/tests.helpers.tsx b/packages/content-management/table_list_view_table/src/__jest__/tests.helpers.tsx index a1f35289c26ef..d1f42f0d1d6b1 100644 --- a/packages/content-management/table_list_view_table/src/__jest__/tests.helpers.tsx +++ b/packages/content-management/table_list_view_table/src/__jest__/tests.helpers.tsx @@ -9,12 +9,13 @@ import React from 'react'; import type { ComponentType } from 'react'; import { from } from 'rxjs'; import { ContentEditorProvider } from '@kbn/content-management-content-editor'; +import { UserProfilesProvider, UserProfilesServices } from '@kbn/content-management-user-profiles'; import { TagList } from '../mocks'; import { TableListViewProvider, Services } from '../services'; -export const getMockServices = (overrides?: Partial) => { - const services: Services = { +export const getMockServices = (overrides?: Partial) => { + const services: Services & UserProfilesServices = { canEditAdvancedSettings: true, getListingLimitSettingsUrl: () => 'http://elastic.co', notifyError: () => undefined, @@ -25,24 +26,29 @@ export const getMockServices = (overrides?: Partial) => { itemHasTags: () => true, getTagManagementUrl: () => '', getTagIdsFromReferences: () => [], - bulkGetUserProfiles: jest.fn(() => Promise.resolve([])), - getUserProfile: jest.fn(), isTaggingEnabled: () => true, + bulkGetUserProfiles: async () => [], + getUserProfile: async () => ({ uid: '', enabled: true, data: {}, user: { username: '' } }), ...overrides, }; return services; }; -export function WithServices

(Comp: ComponentType

, overrides: Partial = {}) { +export function WithServices

( + Comp: ComponentType

, + overrides: Partial = {} +) { return (props: P) => { const services = getMockServices(overrides); return ( - undefined}> - - - - + + undefined}> + + + + + ); }; } diff --git a/packages/content-management/table_list_view_table/src/components/user_filter_panel.tsx b/packages/content-management/table_list_view_table/src/components/user_filter_panel.tsx index 2307f449b9c2d..1f53678936065 100644 --- a/packages/content-management/table_list_view_table/src/components/user_filter_panel.tsx +++ b/packages/content-management/table_list_view_table/src/components/user_filter_panel.tsx @@ -11,10 +11,8 @@ import React from 'react'; import { EuiFilterButton, useEuiTheme } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { UserProfile, UserProfilesPopover } from '@kbn/user-profile-components'; -import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { i18n } from '@kbn/i18n'; -import { useServices } from '../services'; -import { NoUsersTip } from './user_missing_tip'; +import { useUserProfiles, NoCreatorTip } from '@kbn/content-management-user-profiles'; interface Context { enabled: boolean; @@ -25,43 +23,29 @@ interface Context { } const UserFilterContext = React.createContext(null); -const queryClient = new QueryClient({ - defaultOptions: { queries: { retry: false, staleTime: 30 * 60 * 1000 } }, -}); export const UserFilterContextProvider: FC = ({ children, ...props }) => { if (!props.enabled) { return <>{children}; } - return ( - - {children} - - ); + return {children}; }; export const NULL_USER = 'no-user'; export const UserFilterPanel: FC<{}> = () => { - const { bulkGetUserProfiles } = useServices(); const { euiTheme } = useEuiTheme(); const componentContext = React.useContext(UserFilterContext); if (!componentContext) throw new Error('UserFilterPanel must be used within a UserFilterContextProvider'); - if (!bulkGetUserProfiles) - throw new Error('UserFilterPanel must be used with a bulkGetUserProfiles function'); const { onSelectedUsersChange, selectedUsers, showNoUserOption } = componentContext; const [isPopoverOpen, setPopoverOpen] = React.useState(false); const [searchTerm, setSearchTerm] = React.useState(''); - const query = useQuery({ - queryKey: ['user-filter-suggestions', componentContext.allUsers], - queryFn: () => bulkGetUserProfiles(componentContext.allUsers), - enabled: isPopoverOpen, - }); + const query = useUserProfiles(componentContext.allUsers, { enabled: isPopoverOpen }); const usersMap = React.useMemo(() => { if (!query.data) return {}; @@ -138,7 +122,7 @@ export const UserFilterPanel: FC<{}> = () => { id="contentManagement.tableList.listing.userFilter.emptyMessage" defaultMessage="None of the dashboards have creators" /> - {} + {}

), nullOptionLabel: i18n.translate( @@ -148,7 +132,7 @@ export const UserFilterPanel: FC<{}> = () => { } ), nullOptionProps: { - append: , + append: , }, clearButtonLabel: ( ( - - } - /> -); diff --git a/packages/content-management/table_list_view_table/src/mocks.tsx b/packages/content-management/table_list_view_table/src/mocks.tsx index a650d544aaecc..f76954fd497a2 100644 --- a/packages/content-management/table_list_view_table/src/mocks.tsx +++ b/packages/content-management/table_list_view_table/src/mocks.tsx @@ -71,8 +71,6 @@ export const getStoryServices = (params: Params, action: ActionFn = () => {}) => itemHasTags: () => true, getTagManagementUrl: () => '', getTagIdsFromReferences: () => [], - bulkGetUserProfiles: () => Promise.resolve([]), - getUserProfile: jest.fn(), isTaggingEnabled: () => true, ...params, }; diff --git a/packages/content-management/table_list_view_table/src/services.tsx b/packages/content-management/table_list_view_table/src/services.tsx index 7be68fd28be91..5275dd35069cd 100644 --- a/packages/content-management/table_list_view_table/src/services.tsx +++ b/packages/content-management/table_list_view_table/src/services.tsx @@ -20,11 +20,10 @@ import type { MountPoint, OverlayRef } from '@kbn/core-mount-utils-browser'; import type { OverlayFlyoutOpenOptions } from '@kbn/core-overlays-browser'; import type { ThemeServiceStart } from '@kbn/core-theme-browser'; import type { UserProfileServiceStart } from '@kbn/core-user-profile-browser'; -import type { UserProfile } from '@kbn/user-profile-components'; import type { FormattedRelative } from '@kbn/i18n-react'; import { toMountPoint } from '@kbn/react-kibana-mount'; import { RedirectAppLinksKibanaProvider } from '@kbn/shared-ux-link-redirect-app'; -import { createBatcher } from './utils/batcher'; +import { UserProfilesKibanaProvider } from '@kbn/content-management-user-profiles'; import { TAG_MANAGEMENT_APP_URL } from './constants'; import type { Tag } from './types'; @@ -69,9 +68,6 @@ export interface Services { /** Handler to return the url to navigate to the kibana tags management */ getTagManagementUrl: () => string; getTagIdsFromReferences: (references: SavedObjectsReference[]) => string[]; - /** resolve user profiles for the user filter and creator functionality */ - bulkGetUserProfiles: (uids: string[]) => Promise; - getUserProfile: (uid: string) => Promise; } const TableListViewContext = React.createContext(null); @@ -229,51 +225,35 @@ export const TableListViewKibanaProvider: FC< [getTagIdsFromReferences] ); - const bulkGetUserProfiles = useCallback<(userProfileIds: string[]) => Promise>( - async (uids: string[]) => { - if (uids.length === 0) return []; - - return core.userProfile.bulkGet({ uids: new Set(uids), dataPath: 'avatar' }); - }, - [core.userProfile] - ); - - const getUserProfile = useMemo(() => { - return createBatcher({ - fetcher: bulkGetUserProfiles, - resolver: (users, id) => users.find((u) => u.uid === id)!, - }).fetch; - }, [bulkGetUserProfiles]); - return ( - - - application.getUrlForApp('management', { - path: `/kibana/settings?query=savedObjects:listingLimit`, - }) - } - notifyError={(title, text) => { - notifications.toasts.addDanger({ title: toMountPoint(title, startServices), text }); - }} - searchQueryParser={searchQueryParser} - DateFormatterComp={(props) => } - currentAppId$={application.currentAppId$} - navigateToUrl={application.navigateToUrl} - isTaggingEnabled={() => Boolean(savedObjectsTagging)} - getTagList={getTagList} - TagList={TagList} - itemHasTags={itemHasTags} - getTagIdsFromReferences={getTagIdsFromReferences} - getTagManagementUrl={() => core.http.basePath.prepend(TAG_MANAGEMENT_APP_URL)} - bulkGetUserProfiles={bulkGetUserProfiles} - getUserProfile={getUserProfile} - > - {children} - - + + + + application.getUrlForApp('management', { + path: `/kibana/settings?query=savedObjects:listingLimit`, + }) + } + notifyError={(title, text) => { + notifications.toasts.addDanger({ title: toMountPoint(title, startServices), text }); + }} + searchQueryParser={searchQueryParser} + DateFormatterComp={(props) => } + currentAppId$={application.currentAppId$} + navigateToUrl={application.navigateToUrl} + isTaggingEnabled={() => Boolean(savedObjectsTagging)} + getTagList={getTagList} + TagList={TagList} + itemHasTags={itemHasTags} + getTagIdsFromReferences={getTagIdsFromReferences} + getTagManagementUrl={() => core.http.basePath.prepend(TAG_MANAGEMENT_APP_URL)} + > + {children} + + + ); }; diff --git a/packages/content-management/table_list_view_table/src/table_list_view_table.tsx b/packages/content-management/table_list_view_table/src/table_list_view_table.tsx index 6cac7f7db8870..9e69c4e0f4434 100644 --- a/packages/content-management/table_list_view_table/src/table_list_view_table.tsx +++ b/packages/content-management/table_list_view_table/src/table_list_view_table.tsx @@ -27,6 +27,11 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { IHttpFetchError } from '@kbn/core-http-browser'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import { useOpenContentEditor } from '@kbn/content-management-content-editor'; +import { + UserAvatarTip, + ManagedAvatarTip, + NoCreatorTip, +} from '@kbn/content-management-user-profiles'; import type { OpenContentEditorParams, SavedObjectsReference, @@ -47,12 +52,12 @@ import { type SortColumnField, getInitialSorting, saveSorting } from './componen import { useTags } from './use_tags'; import { useInRouterContext, useUrlState } from './use_url_state'; import { RowActions, TableItemsRowActions } from './types'; -import { UserAvatarTip } from './components/user_avatar_tip'; -import { NoUsersTip } from './components/user_missing_tip'; -import { ManagedAvatarTip } from './components/managed_avatar_tip'; interface ContentEditorConfig - extends Pick { + extends Pick< + OpenContentEditorParams, + 'isReadonly' | 'onSave' | 'customValidators' | 'showActivityView' + > { enabled?: boolean; } @@ -506,6 +511,11 @@ function TableListViewTableComp({ title: item.attributes.title, description: item.attributes.description, tags, + createdAt: item.createdAt, + createdBy: item.createdBy, + updatedAt: item.updatedAt, + updatedBy: item.updatedBy, + managed: item.managed, }, entityName, ...contentEditor, @@ -575,7 +585,6 @@ function TableListViewTableComp({ {i18n.translate('contentManagement.tableList.createdByColumnTitle', { defaultMessage: 'Creator', })} - ), render: (field: string, record: { createdBy?: string; managed?: boolean }) => @@ -583,7 +592,9 @@ function TableListViewTableComp({ ) : record.managed ? ( - ) : null, + ) : ( + + ), sortable: false /* createdBy column is not sortable because it doesn't make sense to sort by id*/, width: '100px', @@ -601,7 +612,7 @@ function TableListViewTableComp({ ), sortable: true, - width: '120px', + width: '130px', }); } diff --git a/packages/content-management/table_list_view_table/tsconfig.json b/packages/content-management/table_list_view_table/tsconfig.json index 318c7ce382a9b..09bf8256764d1 100644 --- a/packages/content-management/table_list_view_table/tsconfig.json +++ b/packages/content-management/table_list_view_table/tsconfig.json @@ -33,7 +33,8 @@ "@kbn/content-management-table-list-view-common", "@kbn/user-profile-components", "@kbn/core-user-profile-browser", - "@kbn/react-kibana-mount" + "@kbn/react-kibana-mount", + "@kbn/content-management-user-profiles" ], "exclude": [ "target/**/*" diff --git a/packages/content-management/user_profiles/README.md b/packages/content-management/user_profiles/README.md new file mode 100644 index 0000000000000..e3559c9070f62 --- /dev/null +++ b/packages/content-management/user_profiles/README.md @@ -0,0 +1,3 @@ +# @kbn/content-management-user-profiles + +Shared user profile components for content management components. diff --git a/packages/content-management/user_profiles/index.ts b/packages/content-management/user_profiles/index.ts new file mode 100644 index 0000000000000..bce8d57baddcd --- /dev/null +++ b/packages/content-management/user_profiles/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { UserAvatarTip, NoUpdaterTip, NoCreatorTip, ManagedAvatarTip } from './src/components'; + +export { useUserProfile, useUserProfiles } from './src/queries'; + +export { + UserProfilesKibanaProvider, + type UserProfilesKibanaDependencies, + UserProfilesProvider, + type UserProfilesServices, + useUserProfilesServices, +} from './src/services'; diff --git a/packages/content-management/user_profiles/jest.config.js b/packages/content-management/user_profiles/jest.config.js new file mode 100644 index 0000000000000..464585a818055 --- /dev/null +++ b/packages/content-management/user_profiles/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/packages/content-management/user_profiles'], +}; diff --git a/packages/content-management/user_profiles/kibana.jsonc b/packages/content-management/user_profiles/kibana.jsonc new file mode 100644 index 0000000000000..6422efa40b631 --- /dev/null +++ b/packages/content-management/user_profiles/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/content-management-user-profiles", + "owner": "@elastic/appex-sharedux" +} diff --git a/packages/content-management/user_profiles/package.json b/packages/content-management/user_profiles/package.json new file mode 100644 index 0000000000000..bb5629d86ff0b --- /dev/null +++ b/packages/content-management/user_profiles/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/content-management-user-profiles", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/packages/content-management/user_profiles/src/components/index.ts b/packages/content-management/user_profiles/src/components/index.ts new file mode 100644 index 0000000000000..1f6e2116145b9 --- /dev/null +++ b/packages/content-management/user_profiles/src/components/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { UserAvatarTip } from './user_avatar_tip'; +export { NoUpdaterTip, NoCreatorTip } from './user_missing_tip'; +export { ManagedAvatarTip } from './managed_avatar_tip'; diff --git a/packages/content-management/table_list_view_table/src/components/managed_avatar_tip.tsx b/packages/content-management/user_profiles/src/components/managed_avatar_tip.tsx similarity index 70% rename from packages/content-management/table_list_view_table/src/components/managed_avatar_tip.tsx rename to packages/content-management/user_profiles/src/components/managed_avatar_tip.tsx index 1453a5183e9c6..02e22faa629fb 100644 --- a/packages/content-management/table_list_view_table/src/components/managed_avatar_tip.tsx +++ b/packages/content-management/user_profiles/src/components/managed_avatar_tip.tsx @@ -10,10 +10,16 @@ import React from 'react'; import { EuiAvatar, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -export function ManagedAvatarTip({ entityName }: { entityName: string }) { +export function ManagedAvatarTip({ + entityName = i18n.translate('contentManagement.userProfiles.managedAvatarTip.defaultEntityName', { + defaultMessage: 'object', + }), +}: { + entityName?: string; +}) { return ( { - return getUserProfile(props.uid); - }, - { staleTime: Infinity } - ); + const query = useUserProfile(props.uid); if (query.data) { return ( diff --git a/packages/content-management/user_profiles/src/components/user_missing_tip.tsx b/packages/content-management/user_profiles/src/components/user_missing_tip.tsx new file mode 100644 index 0000000000000..758429b781537 --- /dev/null +++ b/packages/content-management/user_profiles/src/components/user_missing_tip.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiIconTip, IconType } from '@elastic/eui'; +import React from 'react'; + +export const NoCreatorTip = (props: { iconType?: IconType }) => ( + + } + {...props} + /> +); + +export const NoUpdaterTip = (props: { iconType?: string }) => ( + + } + {...props} + /> +); + +const NoUsersTip = ({ + iconType: type = 'questionInCircle', + ...props +}: { + content: React.ReactNode; + iconType?: IconType; +}) => ( + +); diff --git a/packages/content-management/user_profiles/src/queries.ts b/packages/content-management/user_profiles/src/queries.ts new file mode 100644 index 0000000000000..b238a5489d20c --- /dev/null +++ b/packages/content-management/user_profiles/src/queries.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { useQuery } from '@tanstack/react-query'; +import { useUserProfilesServices } from './services'; + +export const userProfileKeys = { + get: (uid: string) => ['user-profile', uid], + bulkGet: (uids: string[]) => ['user-profile', { uids }], +}; + +export const useUserProfile = (uid: string) => { + const { getUserProfile } = useUserProfilesServices(); + const query = useQuery( + userProfileKeys.get(uid), + async () => { + return getUserProfile(uid); + }, + { staleTime: Infinity } + ); + return query; +}; + +export const useUserProfiles = (uids: string[], opts?: { enabled?: boolean }) => { + const { bulkGetUserProfiles } = useUserProfilesServices(); + const query = useQuery({ + queryKey: userProfileKeys.bulkGet(uids), + queryFn: () => bulkGetUserProfiles(uids), + enabled: opts?.enabled ?? true, + }); + return query; +}; diff --git a/packages/content-management/user_profiles/src/services.tsx b/packages/content-management/user_profiles/src/services.tsx new file mode 100644 index 0000000000000..25ea8d4b5acda --- /dev/null +++ b/packages/content-management/user_profiles/src/services.tsx @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import type { UserProfileServiceStart } from '@kbn/core-user-profile-browser'; +import React, { FC, PropsWithChildren, useCallback, useContext, useMemo } from 'react'; +import type { UserProfile } from '@kbn/user-profile-components'; +import { createBatcher } from './utils/batcher'; + +export const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false, staleTime: 30 * 60 * 1000 } }, +}); + +export interface UserProfilesKibanaDependencies { + core: { + userProfile: { + bulkGet: UserProfileServiceStart['bulkGet']; + }; + }; +} + +export interface UserProfilesServices { + bulkGetUserProfiles: (uids: string[]) => Promise; + getUserProfile: (uid: string) => Promise; +} + +const UserProfilesContext = React.createContext(null); + +export const UserProfilesProvider: FC> = ({ + children, + ...services +}) => { + return ( + + {children} + + ); +}; + +export const UserProfilesKibanaProvider: FC> = ({ + children, + core, +}) => { + const bulkGetUserProfiles = useCallback<(userProfileIds: string[]) => Promise>( + async (uids: string[]) => { + if (uids.length === 0) return []; + + return core.userProfile.bulkGet({ uids: new Set(uids), dataPath: 'avatar' }); + }, + [core.userProfile] + ); + + const getUserProfile = useMemo(() => { + return createBatcher({ + fetcher: bulkGetUserProfiles, + resolver: (users, id) => users.find((u) => u.uid === id)!, + }).fetch; + }, [bulkGetUserProfiles]); + + return ( + + {children} + + ); +}; + +export function useUserProfilesServices() { + const context = useContext(UserProfilesContext); + + if (!context) { + throw new Error( + 'UserProfilesContext is missing. Ensure your component or React root is wrapped with ' + ); + } + + return context; +} diff --git a/packages/content-management/table_list_view_table/src/utils/batcher.test.tsx b/packages/content-management/user_profiles/src/utils/batcher.test.tsx similarity index 100% rename from packages/content-management/table_list_view_table/src/utils/batcher.test.tsx rename to packages/content-management/user_profiles/src/utils/batcher.test.tsx diff --git a/packages/content-management/table_list_view_table/src/utils/batcher.ts b/packages/content-management/user_profiles/src/utils/batcher.ts similarity index 100% rename from packages/content-management/table_list_view_table/src/utils/batcher.ts rename to packages/content-management/user_profiles/src/utils/batcher.ts diff --git a/packages/content-management/user_profiles/tsconfig.json b/packages/content-management/user_profiles/tsconfig.json new file mode 100644 index 0000000000000..de0aeff18778f --- /dev/null +++ b/packages/content-management/user_profiles/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/user-profile-components", + "@kbn/core-user-profile-browser", + "@kbn/i18n", + "@kbn/i18n-react", + ] +} diff --git a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx index 2fc8c2d36ee0e..b2493454d4da2 100644 --- a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx @@ -154,6 +154,7 @@ describe('useDashboardListingTable', () => { onSave: expect.any(Function), isReadonly: false, customValidators: expect.any(Object), + showActivityView: true, }, createdByEnabled: true, }; diff --git a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx index 83638b01b190e..659e5e43930ea 100644 --- a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx @@ -42,7 +42,9 @@ const toTableListViewSavedObject = (hit: DashboardItem): DashboardSavedObjectUse type: 'dashboard', id: hit.id, updatedAt: hit.updatedAt!, + createdAt: hit.createdAt, createdBy: hit.createdBy, + updatedBy: hit.updatedBy, references: hit.references, managed: hit.managed, attributes: { @@ -280,6 +282,7 @@ export const useDashboardListingTable = ({ isReadonly: !showWriteControls, onSave: updateItemMeta, customValidators: contentEditorValidators, + showActivityView: true, }, createItem: !showWriteControls || !showCreateDashboardButton ? undefined : createItem, deleteItems: !showWriteControls ? undefined : deleteItems, diff --git a/tsconfig.base.json b/tsconfig.base.json index 9c7e088b966d3..bd6380bf501c4 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -196,6 +196,8 @@ "@kbn/content-management-table-list-view-common/*": ["packages/content-management/table_list_view_common/*"], "@kbn/content-management-table-list-view-table": ["packages/content-management/table_list_view_table"], "@kbn/content-management-table-list-view-table/*": ["packages/content-management/table_list_view_table/*"], + "@kbn/content-management-user-profiles": ["packages/content-management/user_profiles"], + "@kbn/content-management-user-profiles/*": ["packages/content-management/user_profiles/*"], "@kbn/content-management-utils": ["packages/kbn-content-management-utils"], "@kbn/content-management-utils/*": ["packages/kbn-content-management-utils/*"], "@kbn/controls-example-plugin": ["examples/controls_example"], diff --git a/yarn.lock b/yarn.lock index 07416bc65a2e4..abdb1cfe29213 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3545,6 +3545,10 @@ version "0.0.0" uid "" +"@kbn/content-management-user-profiles@link:packages/content-management/user_profiles": + version "0.0.0" + uid "" + "@kbn/content-management-utils@link:packages/kbn-content-management-utils": version "0.0.0" uid "" From cb11a1b004b062af9757f8d838e6d1669d544739 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 18 Jun 2024 11:08:01 -0700 Subject: [PATCH 072/127] [Cloud Security] Adding MSW for mocking server responses in React integration tests (#184555) ## Summary It closes #183977 This PR introduces the MSW library into Kibana and setups for MSW usage with Jest for integration testing of React components in the Cloud Security Posture plugin. It also adds the setup for the initial [handlers](https://mswjs.io/docs/concepts/request-handler/), and configures a test for the `` components using MSW to exemplify how the library works. ### Problem Statement Currently, integration tests for React components that interact with the server are hard to write and maintain, as they often require mocking functions implementation and responses, this can lead to tests that do not accurately verify the intended functionality and can be hard to maintain as the implementation of the functions changes. This leads to situations our team faces now, where due to the difficult maintainability of integration tests, we rely much more on End-to-End tests, and maintaining those many End-to-End comes with its own set of tradeoffs, as oftentimes End-to-End tests are detected by the CI as failing or flaky, and as flakiness can happen in End-to-end tests due to its nature of multiple integrated systems, this concept proposes that it's better to reserve End-to-end tests for the features in the most critical path and tests that test multiple integrated systems as those will benefit most of the end-to-end testing. For all the other tests we should focus on unit and integration tests. ### How MSW works MSW is a library that allows you to mock server responses in your tests, it works by intercepting the requests made by the client and returning the mocked responses, this way we can test how the client behaves in different states of the lifecycle such as loading, error, and success. This proposes that we should use MSW to enhance our integration tests, and give preference to writing integration tests over End-to-End tests whenever possible, but this doesn't mean that we should stop writing end-to-end tests, as end-to-end tests are still important for the features in the most critical path and tests that tests multiple integrated systems. ### MSW Diagram Here's a diagram that shows how MSW works with Jest tests: ```mermaid %%{init:{'themeCSS':' g:nth-of-type(3) rect.actor { fill: #eee; };g:nth-of-type(7) rect.actor { fill: #eee; };'}}%% sequenceDiagram participant ReactComponent as React Component participant API as API participant MSW as MSW Mock Server participant Jest as Jest Test Jest->>ReactComponent: Setup component test and mock providers Jest->>MSW: Setup Mock Server Note over Jest,MSW: start listening for requests activate MSW ReactComponent->>API: Make API Call Note over ReactComponent,API: loading state activate API MSW-->>API: Intercepts API Call deactivate API alt is success MSW-->>ReactComponent: Send Mocked success Response else is error MSW-->>ReactComponent: Send Mocked error Response end deactivate MSW ReactComponent-->>Jest: Receive Mocked data and render ``` ### Documentation - Refer to this [PR](https://github.com/elastic/security-team/pull/9624) containing the documentation of how MSW works and how to use it. - Refer to this [presentation](https://docs.google.com/presentation/d/1KYtBaeDMZrpoU5lnKASm8GvCxhrXVqMKxWgR-Xvaxzc/edit#slide=id.g11f0f180654_1_0) to understand the main motivations behind this proposal. ### How to test it ``` yarn test:jest x-pack/plugins/cloud_security_posture/public/components/no_findings_states.test.tsx ``` ### Screenshot ![image](https://github.com/elastic/kibana/assets/19270322/f0673be2-f087-42b5-8ed6-42ce3159e378) Intercepted requests logged with `{debug: true}`: ![image](https://github.com/elastic/kibana/assets/19270322/b512d486-8a2a-422e-bf26-3c6b60a8c6d2) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 1 + renovate.json | 8 + .../cloud_security_posture/jest.config.js | 9 + .../use_license_management_locator_api.tsx | 20 +- .../components/cloud_posture_page.test.tsx | 17 +- .../public/components/cloud_posture_page.tsx | 10 +- .../components/no_findings_states.test.tsx | 245 ----------------- .../components/no_findings_states/index.ts | 8 + .../no_findings_states.handlers.mock.ts | 20 ++ .../no_findings_states.test.tsx | 163 ++++++++++++ .../no_findings_states.tsx | 46 ++-- .../components/subscription_not_allowed.tsx | 13 +- .../test/fixtures/get_mock_dependencies.ts | 28 ++ .../public/test/mock_server/handlers/index.ts | 15 ++ .../handlers/licensing.handlers.mock.ts | 32 +++ .../public/test/mock_server/mock_server.ts | 174 ++++++++++++ .../mock_server/mock_server_test_provider.tsx | 41 +++ .../public/test/test_provider.tsx | 30 +-- .../benchmarks/benchmarks.handlers.mock.ts | 192 ++++++++++++++ .../routes/status/status.handlers.mock.ts | 251 ++++++++++++++++++ yarn.lock | 205 ++++++++++++-- 21 files changed, 1182 insertions(+), 346 deletions(-) delete mode 100644 x-pack/plugins/cloud_security_posture/public/components/no_findings_states.test.tsx create mode 100644 x-pack/plugins/cloud_security_posture/public/components/no_findings_states/index.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx rename x-pack/plugins/cloud_security_posture/public/components/{ => no_findings_states}/no_findings_states.tsx (90%) create mode 100644 x-pack/plugins/cloud_security_posture/public/test/fixtures/get_mock_dependencies.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/licensing.handlers.mock.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx create mode 100644 x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.handlers.mock.ts create mode 100644 x-pack/plugins/cloud_security_posture/server/routes/status/status.handlers.mock.ts diff --git a/package.json b/package.json index 989341509eb04..338db19ea67a1 100644 --- a/package.json +++ b/package.json @@ -1675,6 +1675,7 @@ "mochawesome-merge": "^4.3.0", "mock-fs": "^5.1.2", "ms-chromium-edge-driver": "^0.5.1", + "msw": "^2.3.1", "multistream": "^4.1.0", "mutation-observer": "^1.0.3", "native-hdr-histogram": "^1.0.0", diff --git a/renovate.json b/renovate.json index 2cb7a55cfb4ae..f0995502bb1bc 100644 --- a/renovate.json +++ b/renovate.json @@ -427,6 +427,14 @@ "prCreation": "not-pending", "minimumReleaseAge": "7 days", "enabled": true + }, + { + "groupName": "MSW", + "matchPackageNames": ["msw"], + "reviewers": ["team:kibana-cloud-security-posture"], + "matchBaseBranches": ["main"], + "labels": ["Team: Cloud Security", "release_note:skip", "backport:skip"], + "enabled": true } ] } diff --git a/x-pack/plugins/cloud_security_posture/jest.config.js b/x-pack/plugins/cloud_security_posture/jest.config.js index eb1e880646e56..82ecbd0c85592 100644 --- a/x-pack/plugins/cloud_security_posture/jest.config.js +++ b/x-pack/plugins/cloud_security_posture/jest.config.js @@ -15,4 +15,13 @@ module.exports = { collectCoverageFrom: [ '/x-pack/plugins/cloud_security_posture/{common,public,server}/**/*.{ts,tsx}', ], + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + transformIgnorePatterns: [ + // ignore all node_modules except the modules below (monaco-editor, monaco-yaml, react-monaco-editor, etc) which requires babel transforms to handle dynamic import() + // since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842) + '[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|monaco-languageserver-types|monaco-marker-data-provider|monaco-worker-manager|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color|langchain|langsmith|@cfworker|gpt-tokenizer|flat|@langchain|msw|@bundled-es-modules))[/\\\\].+\\.js$', + 'packages/kbn-pm/dist/index.js', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith|@langchain))/dist/[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith|@langchain))/dist/util/[/\\\\].+\\.js$', + ], }; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_license_management_locator_api.tsx b/x-pack/plugins/cloud_security_posture/public/common/api/use_license_management_locator_api.tsx index 963d9bfae9834..cbfd64b8e60a8 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_license_management_locator_api.tsx +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_license_management_locator_api.tsx @@ -5,23 +5,21 @@ * 2.0. */ -import { useQuery } from '@tanstack/react-query'; import { useKibana } from '../hooks/use_kibana'; const LICENSE_MANAGEMENT_LOCATOR = 'LICENSE_MANAGEMENT_LOCATOR'; -const getLicenseManagementLocatorKey = 'license_management_url_key'; - +/** + * Hook to get the license management locator + * @returns a callback to navigate to the license management page + */ export const useLicenseManagementLocatorApi = () => { const { share } = useKibana().services; - return useQuery([getLicenseManagementLocatorKey], () => { - const locator = share.url.locators.get(LICENSE_MANAGEMENT_LOCATOR); - // license management does not exist on serverless - if (!locator) return; + const locator = share.url.locators.get(LICENSE_MANAGEMENT_LOCATOR); + + // license management does not exist on serverless + if (!locator) return; - return locator.getUrl({ - page: 'dashboard', - }); - }); + return () => locator.navigate({ page: 'dashboard' }); }; diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx index f2e538194a2fa..05fedd4d8adec 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx @@ -43,12 +43,7 @@ describe('', () => { }) ); - (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: true, - }) - ); + (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(undefined); }); const renderCloudPosturePage = ( @@ -85,7 +80,10 @@ describe('', () => { }) ); + (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(() => 'http://license-url'); + renderCloudPosturePage(); + expect(screen.getByTestId('has_locator')).toBeInTheDocument(); }); @@ -97,12 +95,7 @@ describe('', () => { }) ); - (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: undefined, - }) - ); + (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(undefined); renderCloudPosturePage(); expect(screen.getByTestId('no_locator')).toBeInTheDocument(); diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx index bfcaf85cfc457..b2f1d892da907 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx @@ -15,7 +15,6 @@ import { SubscriptionNotAllowed } from './subscription_not_allowed'; import { useSubscriptionStatus } from '../common/hooks/use_subscription_status'; import { FullSizeCenteredPage } from './full_size_centered_page'; import { CspLoadingState } from './csp_loading_state'; -import { useLicenseManagementLocatorApi } from '../common/api/use_license_management_locator_api'; export const LOADING_STATE_TEST_SUBJECT = 'cloud_posture_page_loading'; export const ERROR_STATE_TEST_SUBJECT = 'cloud_posture_page_error'; @@ -151,9 +150,9 @@ export const defaultNoDataRenderer = () => ( ); -const subscriptionNotAllowedRenderer = (licenseManagementLocator?: string) => ( +const subscriptionNotAllowedRenderer = () => ( - + ); @@ -173,19 +172,18 @@ export const CloudPosturePage = ({ noDataRenderer = defaultNoDataRenderer, }: CloudPosturePageProps) => { const subscriptionStatus = useSubscriptionStatus(); - const getLicenseManagementLocator = useLicenseManagementLocatorApi(); const render = () => { if (subscriptionStatus.isError) { return defaultErrorRenderer(subscriptionStatus.error); } - if (subscriptionStatus.isLoading || getLicenseManagementLocator.isLoading) { + if (subscriptionStatus.isLoading) { return defaultLoadingRenderer(); } if (!subscriptionStatus.data) { - return subscriptionNotAllowedRenderer(getLicenseManagementLocator.data); + return subscriptionNotAllowedRenderer(); } if (!query) { diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.test.tsx deleted file mode 100644 index 840aad9af2e94..0000000000000 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.test.tsx +++ /dev/null @@ -1,245 +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 React from 'react'; -import { render } from '@testing-library/react'; -import { createReactQueryResponse } from '../test/fixtures/react_query'; -import { TestProvider } from '../test/test_provider'; -import { NoFindingsStates } from './no_findings_states'; -import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; -import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link'; -import { useLicenseManagementLocatorApi } from '../common/api/use_license_management_locator_api'; -import { useSubscriptionStatus } from '../common/hooks/use_subscription_status'; - -jest.mock('../common/api/use_setup_status_api', () => ({ - useCspSetupStatusApi: jest.fn(), -})); - -jest.mock('../common/navigation/use_csp_integration_link', () => ({ - useCspIntegrationLink: jest.fn(), -})); - -jest.mock('../common/api/use_license_management_locator_api', () => ({ - useLicenseManagementLocatorApi: jest.fn(), -})); - -jest.mock('../common/hooks/use_subscription_status', () => ({ - useSubscriptionStatus: jest.fn(), -})); - -const customRederer = (postureType: 'cspm' | 'kspm') => { - return render( - - - - ); -}; - -describe('NoFindingsStates', () => { - beforeEach(() => { - jest.clearAllMocks(); - - (useSubscriptionStatus as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: true, - }) - ); - - (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: true, - }) - ); - - (useCspIntegrationLink as jest.Mock).mockReturnValue('http://cspm-or-kspm-integration-link'); - }); - - it('should show the indexing notification when CSPM is not installed and KSPM is indexing', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - cspm: { - status: 'not-deployed', - }, - kspm: { - status: 'indexing', - }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - - const { getByText } = customRederer('kspm'); - expect(getByText(/posture evaluation underway/i)).toBeInTheDocument(); - expect( - getByText( - /waiting for data to be collected and indexed. check back later to see your findings/i - ) - ).toBeInTheDocument(); - }); - - it('should show the indexing notification when KSPM is not installed and CSPM is indexing', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { - status: 'not-deployed', - }, - cspm: { - status: 'indexing', - }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - - const { getByText } = customRederer('cspm'); - expect(getByText(/posture evaluation underway/i)).toBeInTheDocument(); - expect( - getByText( - /waiting for data to be collected and indexed. Check back later to see your findings/i - ) - ).toBeInTheDocument(); - }); - - it('should show the indexing timout notification when CSPM is status is index-timeout', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { - status: 'installed', - }, - cspm: { - status: 'index-timeout', - }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - - const { getByText } = customRederer('cspm'); - expect(getByText(/waiting for findings data/i)).toBeInTheDocument(); - const indexTimeOutMessage = getByText(/collecting findings is taking longer than expected/i); - expect(indexTimeOutMessage).toBeInTheDocument(); - }); - - it('should show the indexing timout notification when KSPM is status is index-timeout', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { - status: 'index-timeout', - }, - cspm: { - status: 'installed', - }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - - const { getByText } = customRederer('kspm'); - expect(getByText(/waiting for findings data/i)).toBeInTheDocument(); - expect(getByText(/collecting findings is taking longer than expected/i)).toBeInTheDocument(); - }); - - it('should show the unprivileged notification when CSPM is status is index-timeout', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { - status: 'installed', - }, - cspm: { - status: 'unprivileged', - }, - indicesDetails: [ - { - index: 'logs-cloud_security_posture.findings_latest-default', - status: 'unprivileged', - }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'unprivileged' }, - ], - }, - }) - ); - - const { getByText } = customRederer('cspm'); - expect(getByText(/privileges required/i)).toBeInTheDocument(); - }); - - it('should show the unprivileged notification when KSPM is status is index-timeout', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { - status: 'unprivileged', - }, - cspm: { - status: 'installed', - }, - indicesDetails: [ - { - index: 'logs-cloud_security_posture.findings_latest-default', - status: 'unprivileged', - }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'unprivileged' }, - ], - }, - }) - ); - - const { getByText } = customRederer('kspm'); - expect(getByText(/privileges required/i)).toBeInTheDocument(); - }); - - it('should show the not-installed notification when CSPM and KSPM status is not-installed', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { - status: 'not-installed', - }, - cspm: { - status: 'not-installed', - }, - indicesDetails: [ - { - index: 'logs-cloud_security_posture.findings_latest-default', - status: 'success', - }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'success' }, - ], - }, - }) - ); - - const { getByText } = customRederer('cspm'); - expect(getByText(/learn more about cloud security posture/i)).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/index.ts b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/index.ts new file mode 100644 index 0000000000000..e136062ed2ccb --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './no_findings_states'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.ts new file mode 100644 index 0000000000000..904083ca86f5c --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { http, HttpResponse } from 'msw'; + +export const fleetCspPackageHandler = http.get( + `/api/fleet/epm/packages/cloud_security_posture`, + () => { + return HttpResponse.json({ + item: { + name: 'cloud_security_posture', + version: '1.9.0', + }, + }); + } +); diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx new file mode 100644 index 0000000000000..ad3e482f614f5 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx @@ -0,0 +1,163 @@ +/* + * Copyright 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 { screen, waitFor } from '@testing-library/react'; +import { setupMockServer, startMockServer } from '../../test/mock_server/mock_server'; +import { renderWrapper } from '../../test/mock_server/mock_server_test_provider'; +import { NoFindingsStates } from './no_findings_states'; +import * as statusHandlers from '../../../server/routes/status/status.handlers.mock'; +import * as benchmarksHandlers from '../../../server/routes/benchmarks/benchmarks.handlers.mock'; +import { fleetCspPackageHandler } from './no_findings_states.handlers.mock'; + +const server = setupMockServer(); + +const renderNoFindingsStates = (postureType: 'cspm' | 'kspm' = 'cspm') => { + return renderWrapper(); +}; + +describe('NoFindingsStates', () => { + startMockServer(server); + + beforeEach(() => { + server.use(fleetCspPackageHandler); + }); + + it('shows integrations installation prompt with installation links when integration is not-installed', async () => { + server.use(statusHandlers.notInstalledHandler); + renderNoFindingsStates(); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => { + expect( + screen.getByText(/detect security misconfigurations in your cloud infrastructure!/i) + ).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByRole('link', { name: /add cspm integration/i })).toHaveAttribute( + 'href', + '/app/fleet/integrations/cloud_security_posture-1.9.0/add-integration/cspm' + ); + }); + + await waitFor(() => { + expect(screen.getByRole('link', { name: /add kspm integration/i })).toHaveAttribute( + 'href', + '/app/fleet/integrations/cloud_security_posture-1.9.0/add-integration/kspm' + ); + }); + }); + it('shows install agent prompt with install agent link when status is not-deployed', async () => { + server.use(statusHandlers.notDeployedHandler); + server.use(benchmarksHandlers.cspmInstalledHandler); + renderNoFindingsStates(); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => { + expect(screen.getByText(/no agents installed/i)).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByRole('link', { name: /install agent/i })).toHaveAttribute( + 'href', + '/app/integrations/detail/cloud_security_posture-1.9.0/policies?addAgentToPolicyId=30cba674-531c-4225-b392-3f7810957511&integration=630f3e42-659e-4499-9007-61e36adf1d97' + ); + }); + }); + it('shows install agent prompt with install agent link when status is not-deployed and postureType is KSPM', async () => { + server.use(statusHandlers.notDeployedHandler); + server.use(benchmarksHandlers.kspmInstalledHandler); + renderNoFindingsStates('kspm'); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => { + expect(screen.getByText(/no agents installed/i)).toBeInTheDocument(); + }); + + await waitFor(() => { + const link = screen.getByRole('link', { + name: /install agent/i, + }); + expect(link).toHaveAttribute( + 'href', + '/app/integrations/detail/cloud_security_posture-1.9.0/policies?addAgentToPolicyId=e2f72eea-bf76-4576-bed8-e29d2df102a7&integration=6aedf856-bc21-49aa-859a-a0952789f898' + ); + }); + }); + it('shows indexing message when status is indexing', async () => { + server.use(statusHandlers.indexingHandler); + + renderNoFindingsStates(); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => { + expect(screen.getByText(/posture evaluation underway/i)).toBeInTheDocument(); + }); + + expect( + screen.getByText( + /waiting for data to be collected and indexed. check back later to see your findings/i + ) + ).toBeInTheDocument(); + }); + it('shows timeout message when status is index-timeout', async () => { + server.use(statusHandlers.indexTimeoutHandler); + + renderNoFindingsStates(); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => { + screen.getByRole('heading', { + name: /waiting for findings data/i, + }); + }); + + expect( + screen.getByText(/collecting findings is taking longer than expected/i) + ).toBeInTheDocument(); + }); + it('shows unprivileged message when status is unprivileged', async () => { + server.use(statusHandlers.unprivilegedHandler); + + renderNoFindingsStates(); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByText(/privileges required/i)).toBeInTheDocument(); + + expect( + screen.getByText(/required elasticsearch index privilege for the following indices:/i) + ).toBeInTheDocument(); + expect( + screen.getByText('logs-cloud_security_posture.findings_latest-default') + ).toBeInTheDocument(); + expect(screen.getByText('logs-cloud_security_posture.findings-default*')).toBeInTheDocument(); + expect(screen.getByText('logs-cloud_security_posture.scores-default')).toBeInTheDocument(); + expect( + screen.getByText('logs-cloud_security_posture.vulnerabilities_latest-default') + ).toBeInTheDocument(); + }); + }); + it('renders empty container when the status does not match a no finding status', async () => { + server.use(statusHandlers.indexedHandler); + + const { container } = renderNoFindingsStates(); + + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => { + expect(screen.queryByText(/loading/i)).not.toBeInTheDocument(); + }); + expect(container).toMatchInlineSnapshot(` +
+
+
+ `); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx similarity index 90% rename from x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx rename to x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx index 8e20207719940..97dfce7b84c1e 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx @@ -20,21 +20,21 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../common/constants'; -import { FullSizeCenteredPage } from './full_size_centered_page'; -import { useCISIntegrationPoliciesLink } from '../common/navigation/use_navigate_to_cis_integration_policies'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; +import { FullSizeCenteredPage } from '../full_size_centered_page'; +import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; import { CSPM_NOT_INSTALLED_ACTION_SUBJ, KSPM_NOT_INSTALLED_ACTION_SUBJ, NO_FINDINGS_STATUS_TEST_SUBJ, -} from './test_subjects'; -import { CloudPosturePage, PACKAGE_NOT_INSTALLED_TEST_SUBJECT } from './cloud_posture_page'; -import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; -import type { IndexDetails, PostureTypes, CspStatusCode } from '../../common/types_old'; -import noDataIllustration from '../assets/illustrations/no_data_illustration.svg'; -import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link'; -import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../common/constants'; -import { cspIntegrationDocsNavigation } from '../common/navigation/constants'; +} from '../test_subjects'; +import { CloudPosturePage, PACKAGE_NOT_INSTALLED_TEST_SUBJECT } from '../cloud_posture_page'; +import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import type { IndexDetails, PostureTypes, CspStatusCode } from '../../../common/types_old'; +import noDataIllustration from '../../assets/illustrations/no_data_illustration.svg'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; +import { NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS } from '../../common/constants'; +import { cspIntegrationDocsNavigation } from '../../common/navigation/constants'; const NotDeployed = ({ postureType }: { postureType: PostureTypes }) => { const integrationPoliciesLink = useCISIntegrationPoliciesLink({ @@ -169,13 +169,10 @@ const Unprivileged = ({ unprivilegedIndices }: { unprivilegedIndices: string[] } /> ); -const EmptySecurityFindingsPrompt = ({ - kspmIntegrationLink, - cspmIntegrationLink, -}: { - kspmIntegrationLink?: string; - cspmIntegrationLink?: string; -}) => { +const EmptySecurityFindingsPrompt = () => { + const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE); + const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE); + return ( { - const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE); - const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE); - const unprivilegedIndices = indicesStatus && indicesStatus @@ -267,13 +263,7 @@ const NoFindingsStatesNotification = ({ return ; if (status === 'indexing' || status === 'waiting_for_results') return ; if (status === 'index-timeout') return ; - if (isNotInstalled) - return ( - - ); + if (isNotInstalled) return ; if (status === 'not-deployed') return ; return null; diff --git a/x-pack/plugins/cloud_security_posture/public/components/subscription_not_allowed.tsx b/x-pack/plugins/cloud_security_posture/public/components/subscription_not_allowed.tsx index a2d8f4fe32c0b..e527a2f9f0c0c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/subscription_not_allowed.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/subscription_not_allowed.tsx @@ -8,12 +8,11 @@ import React from 'react'; import { EuiEmptyPrompt, EuiLink, EuiPageSection } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { useLicenseManagementLocatorApi } from '../common/api/use_license_management_locator_api'; + +export const SubscriptionNotAllowed = () => { + const handleNavigateToLicenseManagement = useLicenseManagementLocatorApi(); -export const SubscriptionNotAllowed = ({ - licenseManagementLocator, -}: { - licenseManagementLocator?: string; -}) => { return ( } body={ - licenseManagementLocator ? ( + handleNavigateToLicenseManagement ? (

+ ({ + data: dataPluginMock.createStartContract(), + unifiedSearch: unifiedSearchPluginMock.createStartContract(), + charts: chartPluginMock.createStartContract(), + discover: discoverPluginMock.createStartContract(), + fleet: fleetMock.createStartMock(), + licensing: licensingMock.createStart(), + uiActions: uiActionsPluginMock.createStartContract(), + storage: sessionStorageMock.create(), + share: sharePluginMock.createStartContract(), +}); diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts new file mode 100644 index 0000000000000..91eb25630b222 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { defaultApiLicensingInfo } from './licensing.handlers.mock'; + +/** + * Default handlers for the mock server, these are the handlers that are always enabled + * when the mock server is started, but can be overridden by specific tests when needed. + * Recommended to use these handlers for common endpoints. + */ +export const defaultHandlers = [defaultApiLicensingInfo]; diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/licensing.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/licensing.handlers.mock.ts new file mode 100644 index 0000000000000..de426f5c72144 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/licensing.handlers.mock.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { http, HttpResponse } from 'msw'; + +export const MOCK_SERVER_LICENSING_INFO_URL = `/api/licensing/info`; + +export const defaultApiLicensingInfo = http.get(MOCK_SERVER_LICENSING_INFO_URL, () => { + const date = new Date(); + const expiryDateInMillis = date.setDate(date.getDate() + 30); + + return HttpResponse.json({ + license: { + uid: '000000-0000-0000-0000-000000000', + type: 'trial', + mode: 'trial', + expiryDateInMillis, + status: 'active', + }, + features: { + security: { + isAvailable: true, + isEnabled: true, + }, + }, + signature: '0000000000000000000000000000000000000000000000000000000', + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts new file mode 100644 index 0000000000000..9fe4b156bc096 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setupServer, SetupServerApi } from 'msw/node'; +import { coreMock } from '@kbn/core/public/mocks'; +import type { CoreStart } from '@kbn/core/public'; +import { licenseMock } from '@kbn/licensing-plugin/common/licensing.mock'; +import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; +import { indexPatternFieldEditorPluginMock as dataViewFieldEditorMock } from '@kbn/data-view-field-editor-plugin/public/mocks'; +import SearchBar from '@kbn/unified-search-plugin/public/search_bar/search_bar'; +import { http, HttpResponse, JsonBodyType } from 'msw'; +import { defaultHandlers } from './handlers'; +import { getMockDependencies } from '../fixtures/get_mock_dependencies'; +import { CspClientPluginStartDeps } from '../../types'; +import { MOCK_SERVER_LICENSING_INFO_URL } from './handlers/licensing.handlers.mock'; + +/** + * Mock the lastValueFrom function from rxjs to return the result of the promise instead of the Observable + * This is for simplifying the testing by avoiding the need to subscribe to the Observable while producing the same result + */ +jest.mock('rxjs', () => { + const actual = jest.requireActual('rxjs'); + return { + ...actual, + lastValueFrom: async (source: Promise) => { + const value = await source; + return value.result; + }, + }; +}); + +/** + * Setup a mock server with the default handlers + * @param debug - If true, log all requests to the console + * @returns The mock server + */ +export const setupMockServer = ({ debug = false }: { debug?: boolean } = {}) => { + const server = setupServer(...defaultHandlers); + + if (debug) { + // Debug: log all requests to the console + server.events.on('request:start', async ({ request }) => { + const payload = await request.clone().text(); + // eslint-disable-next-line no-console + console.log('MSW intercepted request:', request.method, request.url, payload); + }); + server.events.on('response:mocked', async ({ request, response }) => { + const body = await response.json(); + // eslint-disable-next-line no-console + console.log( + '%s %s received %s %s %s', + request.method, + request.url, + response.status, + response.statusText, + JSON.stringify(body, null, 2) + ); + }); + } + return server; +}; + +/** + * This function wraps beforeAll, afterAll and beforeEach for setup MSW server into a single call. + * That makes the describe code further down easier to read and makes + * sure we don't forget the handlers. Can easily be shared between tests. + * @param server - The MSW server instance, created with setupMockServer + */ +export const startMockServer = (server: SetupServerApi) => { + beforeAll(() => server.listen({ onUnhandledRequest: 'warn' })); + afterAll(() => server.close()); + beforeEach(() => { + server.resetHandlers(); + }); +}; + +const MOCK_SERVER_BASE_URL = 'http://localhost'; + +/** + * Get a set of dependencies for the mock server overriding default mock dependencies to perform + * HTTP calls that will be intercepted by the mock server + * @returns The core and deps dependencies used by the KibanaContextProvider + */ +export const getMockServerDependencies = () => { + return { + deps: { + ...getMockDependencies(), + data: { + ...getMockDependencies().data, + search: { + ...getMockDependencies().data.search, + search: async ({ params }: { params: any }) => { + const response = await fetch(`${MOCK_SERVER_BASE_URL}/internal/bsearch`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(params), + }); + return response.json(); + }, + }, + dataViews: { + ...getMockDependencies().data.dataViews, + find: async (pattern: string) => { + const response = await fetch( + `${MOCK_SERVER_BASE_URL}/internal/data_views/fields?pattern=${pattern}` + ); + + const responseJson = await response.json(); + + const fields = responseJson.fields.reduce((acc: any, field: any) => { + acc[field.name] = field; + return acc; + }, {}); + + const dataView = createStubDataView({ + spec: { + id: pattern, + title: pattern, + fields, + }, + }); + + return [dataView]; + }, + }, + }, + licensing: { + ...getMockDependencies().licensing, + refresh: async () => { + const response = await fetch(MOCK_SERVER_LICENSING_INFO_URL); + const responseJson = await response.json(); + return licenseMock.createLicense(responseJson); + }, + }, + dataViewFieldEditor: dataViewFieldEditorMock.createStartContract(), + unifiedSearch: { + ...getMockDependencies().unifiedSearch, + ui: { + ...getMockDependencies().unifiedSearch.ui, + SearchBar, + }, + }, + storage: { + ...getMockDependencies().storage, + get: (key: string) => { + return localStorage.getItem(key); + }, + set: (key: string, value: string) => { + localStorage.setItem(key, value); + }, + }, + } as unknown as Partial, + core: { + ...coreMock.createStart(), + http: { + ...coreMock.createStart().http, + get: async (path: string, options: any) => { + const response = await fetch(`${MOCK_SERVER_BASE_URL}${path}`, options); + return response.json(); + }, + }, + } as unknown as CoreStart, + }; +}; + +export const mockGetRequest = (path: string, response: JsonBodyType) => { + return http.get(path, () => HttpResponse.json(response)); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx new file mode 100644 index 0000000000000..19143d4641836 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/mock_server_test_provider.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import type { CoreStart } from '@kbn/core/public'; +import { CspClientPluginStartDeps } from '../../types'; +import { TestProvider } from '../test_provider'; +import { getMockServerDependencies } from './mock_server'; +interface MockServerDependencies { + deps: Partial; + core: CoreStart; +} + +interface MockServerTestProviderProps { + children: React.ReactNode; + dependencies?: MockServerDependencies; +} + +/** + * Simple wrapper around the TestProvider that provides dependencies for the mock server. + */ +export const MockServerTestProvider = ({ + children, + dependencies = getMockServerDependencies(), +}: MockServerTestProviderProps) => { + return {children}; +}; + +/** + * Renders a component wrapped in the MockServerTestProvider. + */ +export const renderWrapper = (children: React.ReactNode, dependencies?: MockServerDependencies) => { + return render( + {children} + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx b/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx index d677df4258837..ab3173ec8c581 100755 --- a/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx +++ b/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx @@ -6,23 +6,16 @@ */ import type { AppMountParameters, CoreStart } from '@kbn/core/public'; -import React, { useMemo } from 'react'; +import React from 'react'; import { I18nProvider } from '@kbn/i18n-react'; // eslint-disable-next-line no-restricted-imports import { Router } from 'react-router-dom'; import { Route, Routes } from '@kbn/shared-ux-router'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { coreMock } from '@kbn/core/public/mocks'; -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; -import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; -import { fleetMock } from '@kbn/fleet-plugin/public/mocks'; -import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; -import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; -import { sessionStorageMock } from '@kbn/core-http-server-mocks'; import type { CspClientPluginStartDeps } from '../types'; +import { getMockDependencies } from './fixtures/get_mock_dependencies'; interface CspAppDeps { core: CoreStart; @@ -33,20 +26,17 @@ interface CspAppDeps { export const TestProvider: React.FC> = ({ core = coreMock.createStart(), - deps = { - data: dataPluginMock.createStartContract(), - unifiedSearch: unifiedSearchPluginMock.createStartContract(), - charts: chartPluginMock.createStartContract(), - discover: discoverPluginMock.createStartContract(), - fleet: fleetMock.createStartMock(), - licensing: licensingMock.createStart(), - uiActions: uiActionsPluginMock.createStartContract(), - storage: sessionStorageMock.create(), - }, + deps = getMockDependencies(), params = coreMock.createAppMountParameters(), children, } = {}) => { - const queryClient = useMemo(() => new QueryClient(), []); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); return ( diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.handlers.mock.ts new file mode 100644 index 0000000000000..ab9d84fbc5b09 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.handlers.mock.ts @@ -0,0 +1,192 @@ +/* + * Copyright 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 { http, HttpResponse } from 'msw'; + +export const cspmInstalledHandler = http.get('/internal/cloud_security_posture/benchmarks', () => { + return HttpResponse.json({ + items: [ + { + package_policy: { + id: '630f3e42-659e-4499-9007-61e36adf1d97', + name: 'cspm-1', + namespace: 'default', + description: '', + package: { + name: 'cloud_security_posture', + title: 'Security Posture Management', + version: '1.9.0', + }, + enabled: true, + policy_id: '30cba674-531c-4225-b392-3f7810957511', + inputs: [ + { + type: 'cloudbeat/cis_aws', + policy_template: 'cspm', + enabled: true, + streams: [ + { + enabled: true, + data_stream: { + type: 'logs', + dataset: 'cloud_security_posture.findings', + }, + vars: { + access_key_id: { + type: 'text', + }, + secret_access_key: { + type: 'text', + }, + session_token: { + type: 'text', + }, + shared_credential_file: { + type: 'text', + }, + credential_profile_name: { + type: 'text', + }, + role_arn: { + type: 'text', + }, + 'aws.credentials.type': { + type: 'text', + }, + 'aws.account_type': { + value: 'organization-account', + type: 'text', + }, + }, + id: 'cloudbeat/cis_aws-cloud_security_posture.findings-630f3e42-659e-4499-9007-61e36adf1d97', + compiled_stream: { + period: '24h', + config: { + v1: { + type: 'cspm', + deployment: 'aws', + benchmark: 'cis_aws', + aws: { + account_type: 'organization-account', + credentials: { + type: null, + }, + }, + }, + }, + }, + }, + ], + config: { + cloud_formation_template_url: { + value: + 'https://console.aws.amazon.com/cloudformation/home#/stacks/quickcreate?templateURL=https://elastic-cspm-cft.s3.eu-central-1.amazonaws.com/cloudformation-cspm-ACCOUNT_TYPE-8.14.0.yml&stackName=Elastic-Cloud-Security-Posture-Management¶m_EnrollmentToken=FLEET_ENROLLMENT_TOKEN¶m_FleetUrl=FLEET_URL¶m_ElasticAgentVersion=KIBANA_VERSION¶m_ElasticArtifactServer=https://artifacts.elastic.co/downloads/beats/elastic-agent', + }, + }, + }, + ], + vars: { + posture: { + value: 'cspm', + type: 'text', + }, + deployment: { + value: 'aws', + type: 'text', + }, + }, + revision: 1, + created_at: '2024-06-03T21:06:20.786Z', + created_by: 'system', + updated_at: '2024-06-03T21:06:20.786Z', + updated_by: 'system', + }, + agent_policy: { + id: '30cba674-531c-4225-b392-3f7810957511', + name: 'Agent policy 3', + agents: 0, + }, + rules_count: 55, + }, + ], + total: 1, + page: 1, + perPage: 100, + }); +}); + +export const kspmInstalledHandler = http.get('/internal/cloud_security_posture/benchmarks', () => { + return HttpResponse.json({ + items: [ + { + package_policy: { + id: '6aedf856-bc21-49aa-859a-a0952789f898', + version: 'WzE4ODcxLDE0XQ==', + name: 'kspm-1', + namespace: 'default', + description: '', + package: { + name: 'cloud_security_posture', + title: 'Security Posture Management', + version: '1.9.0', + }, + enabled: true, + policy_id: 'e2f72eea-bf76-4576-bed8-e29d2df102a7', + inputs: [ + { + type: 'cloudbeat/cis_k8s', + policy_template: 'kspm', + enabled: true, + streams: [ + { + enabled: true, + data_stream: { + type: 'logs', + dataset: 'cloud_security_posture.findings', + }, + id: 'cloudbeat/cis_k8s-cloud_security_posture.findings-6aedf856-bc21-49aa-859a-a0952789f898', + compiled_stream: { + config: { + v1: { + type: 'kspm', + deployment: 'self_managed', + benchmark: 'cis_k8s', + }, + }, + }, + }, + ], + }, + ], + vars: { + posture: { + value: 'kspm', + type: 'text', + }, + deployment: { + value: 'self_managed', + type: 'text', + }, + }, + revision: 1, + created_at: '2024-06-03T21:23:23.139Z', + created_by: 'system', + updated_at: '2024-06-03T21:23:23.139Z', + updated_by: 'system', + }, + agent_policy: { + id: 'e2f72eea-bf76-4576-bed8-e29d2df102a7', + name: 'Agent policy 1', + agents: 0, + }, + rules_count: 92, + }, + ], + total: 1, + page: 1, + perPage: 100, + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.handlers.mock.ts new file mode 100644 index 0000000000000..0f2b3b9eab640 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.handlers.mock.ts @@ -0,0 +1,251 @@ +/* + * Copyright 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 { http, HttpResponse } from 'msw'; + +const STATUS_URL = `/internal/cloud_security_posture/status`; + +export const notInstalledHandler = http.get(STATUS_URL, () => { + return HttpResponse.json({ + cspm: { + status: 'not-installed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + kspm: { + status: 'not-installed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + vuln_mgmt: { + status: 'not-installed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + indicesDetails: [ + { + index: 'logs-cloud_security_posture.findings_latest-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.findings-default*', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.scores-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.vulnerabilities_latest-default', + status: 'empty', + }, + ], + isPluginInitialized: true, + latestPackageVersion: '1.9.0', + }); +}); + +export const notDeployedHandler = http.get(STATUS_URL, () => { + return HttpResponse.json({ + cspm: { + status: 'not-deployed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + kspm: { + status: 'not-deployed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + vuln_mgmt: { + status: 'not-deployed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + indicesDetails: [ + { + index: 'logs-cloud_security_posture.findings_latest-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.findings-default*', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.scores-default', + status: 'not-empty', + }, + { + index: 'logs-cloud_security_posture.vulnerabilities_latest-default', + status: 'empty', + }, + ], + isPluginInitialized: true, + latestPackageVersion: '1.9.0', + installedPackageVersion: '1.9.0', + }); +}); + +export const indexingHandler = http.get(STATUS_URL, () => { + return HttpResponse.json({ + cspm: { + status: 'indexing', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + kspm: { + status: 'indexing', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + vuln_mgmt: { + status: 'indexing', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + indicesDetails: [ + { + index: 'logs-cloud_security_posture.findings_latest-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.findings-default*', + status: 'not-empty', + }, + { + index: 'logs-cloud_security_posture.scores-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.vulnerabilities_latest-default', + status: 'empty', + }, + ], + isPluginInitialized: true, + latestPackageVersion: '1.9.0', + }); +}); + +export const indexTimeoutHandler = http.get(STATUS_URL, () => { + return HttpResponse.json({ + cspm: { + status: 'index-timeout', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + kspm: { + status: 'index-timeout', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + vuln_mgmt: { + status: 'index-timeout', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + indicesDetails: [ + { + index: 'logs-cloud_security_posture.findings_latest-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.findings-default*', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.scores-default', + status: 'empty', + }, + { + index: 'logs-cloud_security_posture.vulnerabilities_latest-default', + status: 'empty', + }, + ], + isPluginInitialized: true, + latestPackageVersion: '1.9.0', + }); +}); + +export const unprivilegedHandler = http.get(STATUS_URL, () => { + return HttpResponse.json({ + cspm: { + status: 'unprivileged', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + kspm: { + status: 'unprivileged', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + vuln_mgmt: { + status: 'unprivileged', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + indicesDetails: [ + { + index: 'logs-cloud_security_posture.findings_latest-default', + status: 'unprivileged', + }, + { + index: 'logs-cloud_security_posture.findings-default*', + status: 'unprivileged', + }, + { + index: 'logs-cloud_security_posture.scores-default', + status: 'unprivileged', + }, + { + index: 'logs-cloud_security_posture.vulnerabilities_latest-default', + status: 'unprivileged', + }, + ], + isPluginInitialized: true, + latestPackageVersion: '1.9.0', + }); +}); + +export const indexedHandler = http.get(STATUS_URL, () => { + return HttpResponse.json({ + cspm: { + status: 'indexed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + kspm: { + status: 'indexed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + vuln_mgmt: { + status: 'indexed', + healthyAgents: 1, + installedPackagePolicies: 1, + }, + indicesDetails: [ + { + index: 'logs-cloud_security_posture.findings_latest-default', + status: 'not-empty', + }, + { + index: 'logs-cloud_security_posture.findings-default*', + status: 'not-empty', + }, + { + index: 'logs-cloud_security_posture.scores-default', + status: 'not-empty', + }, + { + index: 'logs-cloud_security_posture.vulnerabilities_latest-default', + status: 'not-empty', + }, + ], + isPluginInitialized: true, + latestPackageVersion: '1.9.0', + installedPackageVersion: '1.9.0', + }); +}); diff --git a/yarn.lock b/yarn.lock index abdb1cfe29213..a5738570ec387 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1431,6 +1431,20 @@ resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.2.1.tgz#f8b1fbbe79726a4eafa9772ddde147b57f85d177" integrity sha512-cwwGvLGqvoaOZmoP5+i4v/rbW+rHkguvTehuZyM2p/xpmaNSdT2h3B7kHw33aiffv35t1XrYHIkdJSEkSEMJuA== +"@bundled-es-modules/cookie@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" + integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== + dependencies: + cookie "^0.5.0" + +"@bundled-es-modules/statuses@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" + integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== + dependencies: + statuses "^2.0.1" + "@cbor-extract/cbor-extract-darwin-arm64@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.0.0.tgz#cf0667e4c22111c9d45e16c29964892b12460a76" @@ -2830,6 +2844,43 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@inquirer/confirm@^3.0.0": + version "3.1.8" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.1.8.tgz#db80f23f775d9b980c6de2425dde39f9786bf1d3" + integrity sha512-f3INZ+ca4dQdn+MQiq1yP/mOIR/Oc8BLRYuDh6ciToWd6z4W8yArfzjBCMQ0BPY8PcJKwZxGIt8Z6yNT32eSTw== + dependencies: + "@inquirer/core" "^8.2.1" + "@inquirer/type" "^1.3.2" + +"@inquirer/core@^8.2.1": + version "8.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-8.2.1.tgz#ee92c2bf25f378819f56290f8ed8bfef8c6cc94d" + integrity sha512-TIcuQMn2qrtyYe0j136UpHeYpk7AcR/trKeT/7YY0vRgcS9YSfJuQ2+PudPhSofLLsHNnRYAHScQCcVZrJkMqA== + dependencies: + "@inquirer/figures" "^1.0.2" + "@inquirer/type" "^1.3.2" + "@types/mute-stream" "^0.0.4" + "@types/node" "^20.12.12" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + cli-spinners "^2.9.2" + cli-width "^4.1.0" + mute-stream "^1.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + +"@inquirer/figures@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.2.tgz#a6af5e9f9969efb9ed3469130566315c36506b8a" + integrity sha512-4F1MBwVr3c/m4bAUef6LgkvBfSjzwH+OfldgHqcuacWwSUetFebM2wi58WfG9uk1rR98U6GwLed4asLJbwdV5w== + +"@inquirer/type@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.3.2.tgz#439b0b50c152c89fd369d2a17eff54869b4d79b8" + integrity sha512-5Frickan9c89QbPkSu6I6y8p+9eR6hZkdPahGmNDsTFX8FHLPAozyzCZMKUeW8FyYwnlCKUjqIEqxY+UctARiw== + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -7305,6 +7356,23 @@ resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz#0f164b726869f71da3c594171df5ebc1c4b0a407" integrity sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ== +"@mswjs/cookies@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.0.tgz#1528eb43630caf83a1d75d5332b30e75e9bb1b5b" + integrity sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw== + +"@mswjs/interceptors@^0.29.0": + version "0.29.1" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.29.1.tgz#e77fc58b5188569041d0440b25c9e9ebb1ccd60a" + integrity sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw== + dependencies: + "@open-draft/deferred-promise" "^2.2.0" + "@open-draft/logger" "^0.3.0" + "@open-draft/until" "^2.0.0" + is-node-process "^1.2.0" + outvariant "^1.2.1" + strict-event-emitter "^0.5.1" + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" @@ -7603,6 +7671,24 @@ dependencies: "@octokit/openapi-types" "^18.0.0" +"@open-draft/deferred-promise@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== + +"@open-draft/logger@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== + dependencies: + is-node-process "^1.2.0" + outvariant "^1.4.0" + +"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== + "@opentelemetry/api-metrics@0.31.0", "@opentelemetry/api-metrics@^0.31.0": version "0.31.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api-metrics/-/api-metrics-0.31.0.tgz#0ed4cf4d7c731f968721c2b303eaf5e9fd42f736" @@ -9783,6 +9869,11 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== + "@types/cookiejar@^2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.5.tgz#14a3e83fa641beb169a2dd8422d91c3c345a9a78" @@ -10474,6 +10565,13 @@ resolved "https://registry.yarnpkg.com/@types/mustache/-/mustache-0.8.31.tgz#7c86cbf74f7733f9e3bdc28817623927eb386616" integrity sha512-72flCZJkEJHPwhmpHgg4a0ZBLssMhg5NB0yltRblRlZMo4py3B/u/d7icevc4EeN9MPQUo/dPtuVOoVy9ih6cQ== +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + "@types/nock@^10.0.3": version "10.0.3" resolved "https://registry.yarnpkg.com/@types/nock/-/nock-10.0.3.tgz#dab1d18ffbccfbf2db811dab9584304eeb6e1c4c" @@ -10511,7 +10609,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@14 || 16 || 17", "@types/node@20.10.5", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18.0.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^18.0.0", "@types/node@^18.11.18": +"@types/node@*", "@types/node@14 || 16 || 17", "@types/node@20.10.5", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18.0.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^18.0.0", "@types/node@^18.11.18", "@types/node@^20.12.12": version "20.10.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== @@ -10929,6 +11027,11 @@ resolved "https://registry.yarnpkg.com/@types/stats-lite/-/stats-lite-2.2.0.tgz#bc8190bf9dfa1e16b89eaa2b433c99dff0804de9" integrity sha512-YV6SS4QC+pbzqjMIV8qVSTDOOazgKBLTVaN+7PfuxELjz/eyzc20KwDVGPrbHt2OcYMA7K2ezLB45Cp6DpNOSQ== +"@types/statuses@^2.0.4": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" + integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== + "@types/styled-components@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.0.tgz#24d3412ba5395aa06e14fbc93c52f9454cebd0d6" @@ -11139,6 +11242,11 @@ tapable "^2.2.0" webpack "^5" +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@types/ws@*", "@types/ws@^8.5.1": version "8.5.3" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" @@ -11892,12 +12000,12 @@ ansi-colors@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" - integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: - type-fest "^0.8.1" + type-fest "^0.21.3" ansi-escapes@^6.2.0: version "6.2.1" @@ -13922,7 +14030,7 @@ cli-progress@^3.12.0: dependencies: string-width "^4.2.3" -cli-spinners@^2.2.0, cli-spinners@^2.5.0: +cli-spinners@^2.2.0, cli-spinners@^2.5.0, cli-spinners@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== @@ -13957,6 +14065,11 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + client-only@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -18725,7 +18838,7 @@ graphql-tag@^2.12.6: dependencies: tslib "^2.1.0" -graphql@^16.6.0: +graphql@^16.6.0, graphql@^16.8.1: version "16.8.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== @@ -19081,6 +19194,11 @@ he@1.2.0, he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +headers-polyfill@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" + integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== + heap@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" @@ -20083,6 +20201,11 @@ is-nil@^1.0.0: resolved "https://registry.yarnpkg.com/is-nil/-/is-nil-1.0.1.tgz#2daba29e0b585063875e7b539d071f5b15937969" integrity sha1-LauingtYUGOHXntTnQcfWxWTeWk= +is-node-process@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== + is-npm@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-6.0.0.tgz#b59e75e8915543ca5d881ecff864077cba095261" @@ -23336,6 +23459,29 @@ msgpackr@^1.9.9: optionalDependencies: msgpackr-extract "^3.0.2" +msw@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.1.tgz#bfc73e256ffc2c74ec4381b604abb258df35f32b" + integrity sha512-ocgvBCLn/5l3jpl1lssIb3cniuACJLoOfZu01e3n5dbJrpA5PeeWn28jCLgQDNt6d7QT8tF2fYRzm9JoEHtiig== + dependencies: + "@bundled-es-modules/cookie" "^2.0.0" + "@bundled-es-modules/statuses" "^1.0.1" + "@inquirer/confirm" "^3.0.0" + "@mswjs/cookies" "^1.1.0" + "@mswjs/interceptors" "^0.29.0" + "@open-draft/until" "^2.1.0" + "@types/cookie" "^0.6.0" + "@types/statuses" "^2.0.4" + chalk "^4.1.2" + graphql "^16.8.1" + headers-polyfill "^4.0.2" + is-node-process "^1.2.0" + outvariant "^1.4.2" + path-to-regexp "^6.2.0" + strict-event-emitter "^0.5.1" + type-fest "^4.9.0" + yargs "^17.7.2" + multicast-dns@^7.2.5: version "7.2.5" resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" @@ -23385,6 +23531,11 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + nan@^2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554" @@ -24342,6 +24493,11 @@ ospath@^1.2.2: resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= +outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.2.tgz#f54f19240eeb7f15b28263d5147405752d8e2066" + integrity sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ== + p-all@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" @@ -24737,6 +24893,11 @@ path-to-regexp@^2.2.1: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704" integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w== +path-to-regexp@^6.2.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" + integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -28261,10 +28422,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" - integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== +signal-exit@^4.0.1, signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-bin-help@^1.8.0: version "1.8.0" @@ -28938,7 +29099,7 @@ stats-lite@^2.2.0: dependencies: isnumber "~1.0.0" -statuses@2.0.1: +statuses@2.0.1, statuses@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== @@ -29026,6 +29187,11 @@ streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.0, streamx@^2.13.2, streamx@^2.1 optionalDependencies: bare-events "^2.2.0" +strict-event-emitter@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== + strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -30286,6 +30452,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" @@ -30306,10 +30477,10 @@ type-fest@^2.13.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== -type-fest@^4.15.0, type-fest@^4.17.0: - version "4.17.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.17.0.tgz#4c1b2c2852d2a40ba8c0236d3afc6fc68229e5bf" - integrity sha512-9flrz1zkfLRH3jO3bLflmTxryzKMxVa7841VeMgBaNQGY6vH4RCcpN/sQLB7mQQYh1GZ5utT2deypMuCy4yicw== +type-fest@^4.15.0, type-fest@^4.17.0, type-fest@^4.9.0: + version "4.18.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.18.3.tgz#5249f96e7c2c3f0f1561625f54050e343f1c8f68" + integrity sha512-Q08/0IrpvM+NMY9PA2rti9Jb+JejTddwmwmVQGskAlhtcrw1wsRzoR6ode6mR+OAabNa75w/dxedSUY2mlphaQ== type-is@~1.6.18: version "1.6.18" From 962368ce2fcd190857694496e6ef2d042c4b5424 Mon Sep 17 00:00:00 2001 From: Elastic Machine Date: Wed, 19 Jun 2024 04:41:16 +1000 Subject: [PATCH 073/127] [main] Sync bundled packages with Package Storage (#186399) Automated by https://buildkite.com/elastic/package-storage-infra-kibana-discover-release-branches/builds/846 --- fleet_packages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fleet_packages.json b/fleet_packages.json index da78baac4651a..76dd27e8c27f0 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -30,7 +30,7 @@ }, { "name": "elastic_agent", - "version": "1.19.2" + "version": "1.20.0" }, { "name": "endpoint", From 5a88e4cc37c2b17999cf70aca99a17ac3391cf7a Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Tue, 18 Jun 2024 20:50:21 +0200 Subject: [PATCH 074/127] [Security Solution] Support local OpenAPI circular references by code generation (#186221) **Addresses:** https://github.com/elastic/kibana/issues/186066 ## Summary This PR adds `kbn-openapi-generator` support for local OpenAPI circular references. ## Details Circular references represent a problem for OpenAPI adoption since lack of support forces engineers to disable code generation and manually define Zod schemas and related TS types. This PR brings `kbn-openapi-generator` support for local OpenAPI circular references. Local references means references to schemas inside one document which looks like `#/components/schemas/MySchema`. It should cover the majority of cases when circular references support id required. The feature is implemented by detecting local circular references and applying a different generation template for involved in cycles inspired by [Zod recursive types docs section](https://github.com/colinhacks/zod?tab=readme-ov-file#recursive-types) for schemas. It involves TS types generation since TS isn't able to properly infer types in this case and hinting circular Zod schemas via `z.ZodType<>`. On top of that circular schema usages are wrapped in `z.lazy()`. ## What's not implemented? - Multi-file circular references aren't supported ## How to test Security Solution doesn't have OpenAPI circular schemas yet. But generator's behavior has been verified on the following specs - Self-recursive Spec: ```yaml components: x-codegen-enabled: true schemas: SelfRecursive: type: object properties: fieldA: $ref: '#/components/schemas/SelfRecursive' ``` Generated output: ```ts import type { ZodTypeDef } from 'zod'; import { z } from 'zod'; export interface SchemaA { fieldA?: SchemaA; } export interface SchemaAInput { fieldA?: SchemaAInput; } export const SchemaA: z.ZodType = z.object({ fieldA: z.lazy(() => SchemaA).optional(), }); ``` - Two circular schemas Spec: ```yaml components: x-codegen-enabled: true schemas: SchemaA: type: object properties: recursiveFieldB: $ref: '#/components/schemas/SchemaB' SchemaB: type: object properties: recursiveFieldA: $ref: '#/components/schemas/SchemaA' ``` Generated output: ```ts import type { ZodTypeDef } from 'zod'; import { z } from 'zod'; export interface SchemaA { recursiveFieldB?: SchemaB; } export interface SchemaAInput { recursiveFieldB?: SchemaBInput; } export const SchemaA: z.ZodType = z.object({ recursiveFieldB: z.lazy(() => SchemaB).optional(), }); export interface SchemaB { recursiveFieldA?: SchemaA; } export interface SchemaBInput { recursiveFieldA?: SchemaAInput; } export const SchemaB: z.ZodType = z.object({ recursiveFieldA: z.lazy(() => SchemaA).optional(), }); ``` - More complex example with circular with `anyOf` and non circular schemas Spec: ```yaml components: x-codegen-enabled: true schemas: SchemaA: anyOf: - $ref: '#/components/schemas/SchemaB' - $ref: '#/components/schemas/SchemaC' - type: string enum: [valueA, valueB] SchemaB: type: object properties: fieldB: $ref: '#/components/schemas/SchemaC' defaultableField: type: number default: 1 required: [fieldB] SchemaC: type: object properties: fieldC: $ref: '#/components/schemas/SchemaA' SchemaZ: anyOf: - type: object properties: fieldZ: type: string defField: type: number default: 1 required: [fieldZ] - type: object properties: fieldX: type: boolean required: [fieldX] ``` Generated output: ```ts import type { ZodTypeDef } from 'zod'; import { z } from 'zod'; export type SchemaA = SchemaB | SchemaC | 'valueA' | 'valueB'; export type SchemaAInput = SchemaBInput | SchemaCInput | 'valueA' | 'valueB'; export const SchemaA: z.ZodType = z.union([ z.lazy(() => SchemaB), z.lazy(() => SchemaC), z.enum(['valueA', 'valueB']), ]); export interface SchemaB { fieldB: SchemaC; defaultableField: number; } export interface SchemaBInput { fieldB: SchemaCInput; defaultableField?: number; } export const SchemaB: z.ZodType = z.object({ fieldB: z.lazy(() => SchemaC), defaultableField: z.number().optional().default(1), }); export interface SchemaC { fieldC?: SchemaA; } export interface SchemaCInput { fieldC?: SchemaAInput; } export const SchemaC: z.ZodType = z.object({ fieldC: z.lazy(() => SchemaA).optional(), }); export type SchemaZ = z.infer; export const SchemaZ = z.union([ z.object({ fieldZ: z.string(), defField: z.number().optional().default(1), }), z.object({ fieldX: z.boolean(), }), ]); ``` - Real life example provided by @bhapas while working on OpenAPI specs for Integration Assistant APIs Spec: ```yaml components: x-codegen-enabled: true schemas: ESProcessorItem: type: object description: Processor item for the Elasticsearch processor. additionalProperties: $ref: '#/components/schemas/ESProcessorOptions' ESProcessorOptions: type: object description: Processor options for the Elasticsearch processor. properties: on_failure: type: array items: $ref: '#/components/schemas/ESProcessorItem' description: An array of items to execute if the processor fails. ignore_failure: type: boolean description: If true, the processor continues to the next processor if the current processor fails. ignore_missing: type: boolean description: If true, the processor continues to the next processor if the field is missing. if: type: string description: Conditionally execute the processor. tag: type: string description: A tag to assign to the document after processing. additionalProperties: true ``` Generated output: ```ts import type { ZodTypeDef } from 'zod'; import { z } from 'zod'; /** * Processor item for the Elasticsearch processor. */ export interface ESProcessorItem { [key: string]: ESProcessorOptions; } export interface ESProcessorItemInput { [key: string]: ESProcessorOptionsInput; } export const ESProcessorItem: z.ZodType = z .object({}) .catchall(z.lazy(() => ESProcessorOptions)); /** * Processor options for the Elasticsearch processor. */ export interface ESProcessorOptions { /** * An array of items to execute if the processor fails. */ on_failure?: ESProcessorItem[]; /** * If true, the processor continues to the next processor if the current processor fails. */ ignore_failure?: boolean; /** * If true, the processor continues to the next processor if the field is missing. */ ignore_missing?: boolean; /** * Conditionally execute the processor. */ if?: string; /** * A tag to assign to the document after processing. */ tag?: string; [key: string]: unknown; } export interface ESProcessorOptionsInput { /** * An array of items to execute if the processor fails. */ on_failure?: ESProcessorItemInput[]; /** * If true, the processor continues to the next processor if the current processor fails. */ ignore_failure?: boolean; /** * If true, the processor continues to the next processor if the field is missing. */ ignore_missing?: boolean; /** * Conditionally execute the processor. */ if?: string; /** * A tag to assign to the document after processing. */ tag?: string; [key: string]: unknown; } export const ESProcessorOptions: z.ZodType< ESProcessorOptions, ZodTypeDef, ESProcessorOptionsInput > = z .object({ /** * An array of items to execute if the processor fails. */ on_failure: z.array(z.lazy(() => ESProcessorItem)).optional(), /** * If true, the processor continues to the next processor if the current processor fails. */ ignore_failure: z.boolean().optional(), /** * If true, the processor continues to the next processor if the field is missing. */ ignore_missing: z.boolean().optional(), /** * Conditionally execute the processor. */ if: z.string().optional(), /** * A tag to assign to the document after processing. */ tag: z.string().optional(), }) .catchall(z.unknown()); ``` --- .../src/openapi_generator.ts | 1 + .../src/parser/get_generation_context.ts | 4 + .../src/parser/lib/find_refs.ts | 28 +++++ .../src/parser/lib/get_circular_refs.ts | 105 ++++++++++++++++++ .../src/parser/lib/get_imports_map.ts | 30 +---- .../lib/helpers/extract_by_json_pointer.ts | 47 ++++++++ .../src/parser/lib/helpers/has_ref.ts | 19 ++++ .../lib/helpers/is_plain_object_type.ts | 14 +++ .../src/parser/lib/helpers/plain_object.ts | 9 ++ .../lib/{ => helpers}/traverse_object.ts | 0 .../src/parser/lib/normalize_schema.ts | 56 ++++------ .../src/template_service/register_helpers.ts | 37 +++++- .../templates/ts_input_type.handlebars | 84 ++++++++++++++ .../templates/ts_type.handlebars | 84 ++++++++++++++ .../templates/zod_operation_schema.handlebars | 11 +- .../templates/zod_schema_item.handlebars | 13 +-- 16 files changed, 468 insertions(+), 74 deletions(-) create mode 100644 packages/kbn-openapi-generator/src/parser/lib/find_refs.ts create mode 100644 packages/kbn-openapi-generator/src/parser/lib/get_circular_refs.ts create mode 100644 packages/kbn-openapi-generator/src/parser/lib/helpers/extract_by_json_pointer.ts create mode 100644 packages/kbn-openapi-generator/src/parser/lib/helpers/has_ref.ts create mode 100644 packages/kbn-openapi-generator/src/parser/lib/helpers/is_plain_object_type.ts create mode 100644 packages/kbn-openapi-generator/src/parser/lib/helpers/plain_object.ts rename packages/kbn-openapi-generator/src/parser/lib/{ => helpers}/traverse_object.ts (100%) create mode 100644 packages/kbn-openapi-generator/src/template_service/templates/ts_input_type.handlebars create mode 100644 packages/kbn-openapi-generator/src/template_service/templates/ts_type.handlebars diff --git a/packages/kbn-openapi-generator/src/openapi_generator.ts b/packages/kbn-openapi-generator/src/openapi_generator.ts index bdbc8ecec3c97..b5e73613139aa 100644 --- a/packages/kbn-openapi-generator/src/openapi_generator.ts +++ b/packages/kbn-openapi-generator/src/openapi_generator.ts @@ -100,6 +100,7 @@ export const generate = async (config: GeneratorConfig) => { version: 'Bundle (no version)', }, imports: {}, + circularRefs: new Set(), }); await fs.writeFile(bundle.outFile, result); diff --git a/packages/kbn-openapi-generator/src/parser/get_generation_context.ts b/packages/kbn-openapi-generator/src/parser/get_generation_context.ts index 7f161c0bc7645..2813ff85201e0 100644 --- a/packages/kbn-openapi-generator/src/parser/get_generation_context.ts +++ b/packages/kbn-openapi-generator/src/parser/get_generation_context.ts @@ -13,12 +13,14 @@ import { getImportsMap, ImportsMap } from './lib/get_imports_map'; import { normalizeSchema } from './lib/normalize_schema'; import { NormalizedOperation, OpenApiDocument } from './openapi_types'; import { getInfo } from './lib/get_info'; +import { getCircularRefs } from './lib/get_circular_refs'; export interface GenerationContext { components: OpenAPIV3.ComponentsObject | undefined; operations: NormalizedOperation[]; info: OpenAPIV3.InfoObject; imports: ImportsMap; + circularRefs: Set; } export function getGenerationContext(document: OpenApiDocument): GenerationContext { @@ -28,11 +30,13 @@ export function getGenerationContext(document: OpenApiDocument): GenerationConte const operations = getApiOperationsList(normalizedDocument); const info = getInfo(normalizedDocument); const imports = getImportsMap(normalizedDocument); + const circularRefs = getCircularRefs(normalizedDocument); return { components, operations, info, imports, + circularRefs, }; } diff --git a/packages/kbn-openapi-generator/src/parser/lib/find_refs.ts b/packages/kbn-openapi-generator/src/parser/lib/find_refs.ts new file mode 100644 index 0000000000000..1829c0a5e7ee2 --- /dev/null +++ b/packages/kbn-openapi-generator/src/parser/lib/find_refs.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 { hasRef } from './helpers/has_ref'; +import { traverseObject } from './helpers/traverse_object'; + +/** + * Traverse the OpenAPI document recursively and find all references + * + * @param obj Any object + * @returns A list of external references + */ +export function findRefs(obj: unknown): string[] { + const refs: string[] = []; + + traverseObject(obj, (element) => { + if (hasRef(element)) { + refs.push(element.$ref); + } + }); + + return refs; +} diff --git a/packages/kbn-openapi-generator/src/parser/lib/get_circular_refs.ts b/packages/kbn-openapi-generator/src/parser/lib/get_circular_refs.ts new file mode 100644 index 0000000000000..da9649d5f0c6d --- /dev/null +++ b/packages/kbn-openapi-generator/src/parser/lib/get_circular_refs.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { OpenApiDocument } from '../openapi_types'; +import type { PlainObject } from './helpers/plain_object'; +import { extractByJsonPointer } from './helpers/extract_by_json_pointer'; +import { findRefs } from './find_refs'; + +/** + * Extracts circular references from a provided document. + * Currently only local references are supported. + */ +export function getCircularRefs(document: OpenApiDocument): Set { + const localRefs = findLocalRefs(document); + const circularRefs = new Set(); + const resolveLocalRef = (localRef: string): PlainObject => + extractByJsonPointer(document, extractJsonPointer(localRef)); + + // In general references represent a disconnected graph. To find + // all references cycles we need to check each reference. + for (const startRef of new Set(localRefs)) { + const cycleHeadRef = findCycleHeadRef(startRef, resolveLocalRef); + + if (cycleHeadRef) { + circularRefs.add(cycleHeadRef); + } + } + + return circularRefs; +} + +/** + * Searches for a cycle head. A search starts from `startRef` reference. + * + * A cycle head is a first ref in a cycle. If `startRef` inside a cycle + * a cycle head is the starting ref. It can be illustrated as + * + * c1 - c2 - c3 + * / | + * r1 -> r2 -> r3 -> head c4 + * \ | + * c7 - c6 - c5 + * + * On the schema above references `r1`, `r2` and `r3` depend on the cycle but + * aren't part of the cycle. When search is started from them `head` is + * returned. If a search starts from `c3` then `c3` will be returned. + * + * @param startRef A starting point to find a cycle + * @param resolveRef A callback function to resolve an encountered reference. + * It should return a document node the provided ref resolves to. + * @returns a Set representing a cycle or an empty set if a cycle is not found + */ +function findCycleHeadRef( + startRef: string, + resolveRef: (ref: string) => PlainObject +): string | undefined { + let result: string | undefined; + + const visitedRefs = new Set(); + const search = (ref: string): void => { + if (visitedRefs.has(ref)) { + result = ref; + return; + } + + const refNode = resolveRef(ref); + const nextRefs = findLocalRefs(refNode); + + visitedRefs.add(ref); + nextRefs.forEach(search); + visitedRefs.delete(ref); + }; + + search(startRef); + + return result; +} + +/** + * Finds local references + */ +function findLocalRefs(obj: unknown): string[] { + return findRefs(obj).filter((ref) => isLocalRef(ref)); +} + +/** + * Checks whether the provided ref is local. + * Local references start with `#/` + */ +function isLocalRef(ref: string): boolean { + return ref.startsWith('#/'); +} + +/** + * Extracts a JSON Pointer from a local reference + * by getting rid of the leading slash + */ +function extractJsonPointer(ref: string): string { + return ref.substring(1); +} diff --git a/packages/kbn-openapi-generator/src/parser/lib/get_imports_map.ts b/packages/kbn-openapi-generator/src/parser/lib/get_imports_map.ts index c2259052e0cb6..634ac82aaae8c 100644 --- a/packages/kbn-openapi-generator/src/parser/lib/get_imports_map.ts +++ b/packages/kbn-openapi-generator/src/parser/lib/get_imports_map.ts @@ -8,7 +8,7 @@ import { uniq } from 'lodash'; import type { OpenApiDocument } from '../openapi_types'; -import { traverseObject } from './traverse_object'; +import { findRefs } from './find_refs'; export interface ImportsMap { [importPath: string]: string[]; @@ -37,31 +37,3 @@ export const getImportsMap = (parsedSchema: OpenApiDocument): ImportsMap => { return importMap; }; - -/** - * Check if an object has a $ref property - * - * @param obj Any object - * @returns True if the object has a $ref property - */ -const hasRef = (obj: unknown): obj is { $ref: string } => { - return typeof obj === 'object' && obj !== null && '$ref' in obj; -}; - -/** - * Traverse the OpenAPI document recursively and find all references - * - * @param obj Any object - * @returns A list of external references - */ -function findRefs(obj: unknown): string[] { - const refs: string[] = []; - - traverseObject(obj, (element) => { - if (hasRef(element)) { - refs.push(element.$ref); - } - }); - - return refs; -} diff --git a/packages/kbn-openapi-generator/src/parser/lib/helpers/extract_by_json_pointer.ts b/packages/kbn-openapi-generator/src/parser/lib/helpers/extract_by_json_pointer.ts new file mode 100644 index 0000000000000..bdfe59965b576 --- /dev/null +++ b/packages/kbn-openapi-generator/src/parser/lib/helpers/extract_by_json_pointer.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { PlainObject } from './plain_object'; +import { isPlainObjectType } from './is_plain_object_type'; + +/** + * Extract a node from a document using a provided [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901). + * + * JSON Pointer is the second part in [JSON Reference](https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03). + * For example an object `{ $ref: "./some-file.yaml#/components/schemas/MySchema"}` is a reference node. + * Where `/components/schemas/MySchema` is a JSON pointer. `./some-file.yaml` is a document reference. + * Yaml shares the same JSON reference standard and basically can be considered just as a different + * JS Object serialization format. See OpenAPI [Using $ref](https://swagger.io/docs/specification/using-ref/) for more information. + * + * @param document a document containing node to resolve by using the pointer + * @param pointer a JSON Pointer + * @returns resolved document node (it's always a JS object) + */ +export function extractByJsonPointer(document: unknown, pointer: string): PlainObject { + if (!pointer.startsWith('/')) { + throw new Error('$ref pointer must start with a leading slash'); + } + + if (!isPlainObjectType(document)) { + throw new Error('document must be an object'); + } + + let target = document; + + for (const segment of pointer.slice(1).split('/')) { + const nextTarget = target[segment]; + + if (!isPlainObjectType(nextTarget)) { + throw new Error(`JSON Pointer "${pointer}" is not found in "${JSON.stringify(document)}"`); + } + + target = nextTarget; + } + + return target; +} diff --git a/packages/kbn-openapi-generator/src/parser/lib/helpers/has_ref.ts b/packages/kbn-openapi-generator/src/parser/lib/helpers/has_ref.ts new file mode 100644 index 0000000000000..4457665070f7b --- /dev/null +++ b/packages/kbn-openapi-generator/src/parser/lib/helpers/has_ref.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 { NormalizedReferenceObject } from '../../openapi_types'; + +/** + * Check if an object has a $ref property + * + * @param obj Any object + * @returns True if the object has a $ref property + */ +export function hasRef(obj: unknown): obj is NormalizedReferenceObject { + return typeof obj === 'object' && obj !== null && '$ref' in obj; +} diff --git a/packages/kbn-openapi-generator/src/parser/lib/helpers/is_plain_object_type.ts b/packages/kbn-openapi-generator/src/parser/lib/helpers/is_plain_object_type.ts new file mode 100644 index 0000000000000..c3612443800e9 --- /dev/null +++ b/packages/kbn-openapi-generator/src/parser/lib/helpers/is_plain_object_type.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { isPlainObject } from 'lodash'; +import type { PlainObject } from './plain_object'; + +export function isPlainObjectType(maybeObj: unknown): maybeObj is PlainObject { + return isPlainObject(maybeObj); +} diff --git a/packages/kbn-openapi-generator/src/parser/lib/helpers/plain_object.ts b/packages/kbn-openapi-generator/src/parser/lib/helpers/plain_object.ts new file mode 100644 index 0000000000000..8a3fead0f8b80 --- /dev/null +++ b/packages/kbn-openapi-generator/src/parser/lib/helpers/plain_object.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 type PlainObject = Record; diff --git a/packages/kbn-openapi-generator/src/parser/lib/traverse_object.ts b/packages/kbn-openapi-generator/src/parser/lib/helpers/traverse_object.ts similarity index 100% rename from packages/kbn-openapi-generator/src/parser/lib/traverse_object.ts rename to packages/kbn-openapi-generator/src/parser/lib/helpers/traverse_object.ts diff --git a/packages/kbn-openapi-generator/src/parser/lib/normalize_schema.ts b/packages/kbn-openapi-generator/src/parser/lib/normalize_schema.ts index 0ed02a28585eb..d082b9a96dc44 100644 --- a/packages/kbn-openapi-generator/src/parser/lib/normalize_schema.ts +++ b/packages/kbn-openapi-generator/src/parser/lib/normalize_schema.ts @@ -7,41 +7,31 @@ */ import { OpenAPIV3 } from 'openapi-types'; -import { NormalizedReferenceObject } from '../openapi_types'; -import { traverseObject } from './traverse_object'; - -/** - * Check if an object has a $ref property - * - * @param obj Any object - * @returns True if the object has a $ref property - */ -const hasRef = (obj: unknown): obj is NormalizedReferenceObject => { - return typeof obj === 'object' && obj !== null && '$ref' in obj; -}; - -const stringIsUrl = (str: string) => { - try { - new URL(str); - return true; - } catch { - return false; - } -}; - -export function normalizeSchema(schema: OpenAPIV3.Document) { +import { URL } from 'node:url'; +import { traverseObject } from './helpers/traverse_object'; +import { hasRef } from './helpers/has_ref'; + +function isUrl(maybeUrl: string): boolean { + return URL.canParse(maybeUrl); +} + +export function normalizeSchema(schema: OpenAPIV3.Document): OpenAPIV3.Document { traverseObject(schema, (element) => { - if (hasRef(element)) { - if (stringIsUrl(element.$ref)) { - throw new Error(`URL references are not supported: ${element.$ref}`); - } - const referenceName = element.$ref.split('/').pop(); - if (!referenceName) { - throw new Error(`Cannot parse reference name: ${element.$ref}`); - } - - element.referenceName = referenceName; + if (!hasRef(element)) { + return; + } + + if (isUrl(element.$ref)) { + throw new Error(`URL references are not supported: ${element.$ref}`); } + + const referenceName = element.$ref.split('/').pop(); + + if (!referenceName) { + throw new Error(`Cannot parse reference name: ${element.$ref}`); + } + + element.referenceName = referenceName; }); return schema; diff --git a/packages/kbn-openapi-generator/src/template_service/register_helpers.ts b/packages/kbn-openapi-generator/src/template_service/register_helpers.ts index c676ae869c7ab..55f2d9d60f37a 100644 --- a/packages/kbn-openapi-generator/src/template_service/register_helpers.ts +++ b/packages/kbn-openapi-generator/src/template_service/register_helpers.ts @@ -7,6 +7,7 @@ */ import type Handlebars from '@kbn/handlebars'; +import { HelperOptions } from 'handlebars'; import { snakeCase, camelCase } from 'lodash'; export function registerHelpers(handlebarsInstance: typeof Handlebars) { @@ -47,13 +48,43 @@ export function registerHelpers(handlebarsInstance: typeof Handlebars) { handlebarsInstance.registerHelper('isUnknown', (val: object) => { return !('type' in val || '$ref' in val || 'anyOf' in val || 'oneOf' in val || 'allOf' in val); }); - handlebarsInstance.registerHelper('startsWithSpecialChar', (val: string) => { - return /^[^a-zA-Z0-9]/.test(val); - }); handlebarsInstance.registerHelper( 'replace', (val: string, searchValue: string, replaceValue: string) => { return val.replace(searchValue, replaceValue); } ); + + /** + * Checks whether provided reference is a known circular reference or a part of circular chain. + * + * It's expected that `context.recursiveRefs` has been filled by the parser. + */ + handlebarsInstance.registerHelper('isCircularRef', (ref: string, options: HelperOptions) => { + if (!options.data?.root?.circularRefs) { + return false; + } + + const circularRefs: Set = options.data.root.circularRefs; + + return circularRefs.has(ref); + }); + + /** + * Checks whether provided schema is circular or a part of the circular chain. + * + * It's expected that `context.circularRefs` has been filled by the parser. + */ + handlebarsInstance.registerHelper( + 'isCircularSchema', + (schemaName: string, options: HelperOptions) => { + if (!options.data?.root?.circularRefs) { + return false; + } + + const circularRefs: Set = options.data.root.circularRefs; + + return circularRefs.has(`#/components/schemas/${schemaName}`); + } + ); } diff --git a/packages/kbn-openapi-generator/src/template_service/templates/ts_input_type.handlebars b/packages/kbn-openapi-generator/src/template_service/templates/ts_input_type.handlebars new file mode 100644 index 0000000000000..453e4cdf452d5 --- /dev/null +++ b/packages/kbn-openapi-generator/src/template_service/templates/ts_input_type.handlebars @@ -0,0 +1,84 @@ +{{~#if type~}} + {{~> (concat "type_" type)~}} +{{~/if~}} + +{{~#if $ref~}} + {{referenceName}}Input + {{~#if nullable}} | null {{/if~}} +{{~/if~}} + +{{~#if allOf~}} + {{~#each allOf~}} + {{~> ts_input_type ~}} + {{~#unless @last~}}&{{~/unless~}} + {{~/each~}} +{{~/if~}} + +{{~#if anyOf~}} + {{~#each anyOf~}} + {{~> ts_input_type ~}} + {{~#unless @last~}}|{{~/unless~}} + {{~/each~}} +{{~/if~}} + +{{~#if oneOf~}} + {{~#each oneOf~}} + {{~> ts_input_type ~}} + {{~#unless @last~}}|{{~/unless~}} + {{~/each~}} +{{~/if~}} + +{{#if (isUnknown .)}} +unknown +{{/if}} + +{{~#*inline "type_array"~}} + ({{~> ts_input_type items ~}})[] +{{~/inline~}} + +{{~#*inline "type_boolean"~}} + boolean +{{~/inline~}} + +{{~#*inline "type_integer"~}} + number +{{~/inline~}} + +{{~#*inline "type_number"~}} + number +{{~/inline~}} + +{{~#*inline "type_object"~}} + {{~#if (eq x-modify "required")}} Required< {{/if~}} + {{~#if (eq x-modify "partial")}} Partial< {{/if~}} + { + {{#each properties}} + {{#if description}} + /** + * {{{description}}} + */ + {{/if}} + '{{@key}}'{{~#unless (includes ../required @key)}}?{{/unless~}}: {{> ts_input_type }}; + {{/each}} + {{~#if additionalProperties}} + {{~#if (eq additionalProperties true)~}} + [key: string]: unknown; + {{~else~}} + [key: string]: {{> ts_input_type additionalProperties}}; + {{~/if~}} + {{~/if~}} + } + {{~#if (eq x-modify "partial")}} > {{/if~}} + {{~#if (eq x-modify "required")}} > {{/if~}} +{{~/inline~}} + +{{~#*inline "type_string"~}} + {{~#if enum~}} + {{~#each enum~}} + '{{.}}' + {{~#unless @last~}}|{{~/unless~}} + {{~/each~}} + {{~else~}} + string + {{~/if~}} +{{~/inline~}} diff --git a/packages/kbn-openapi-generator/src/template_service/templates/ts_type.handlebars b/packages/kbn-openapi-generator/src/template_service/templates/ts_type.handlebars new file mode 100644 index 0000000000000..5017af3aa5df0 --- /dev/null +++ b/packages/kbn-openapi-generator/src/template_service/templates/ts_type.handlebars @@ -0,0 +1,84 @@ +{{~#if type~}} + {{~> (concat "type_" type)~}} +{{~/if~}} + +{{~#if $ref~}} + {{referenceName}} + {{~#if nullable}} | null {{/if~}} +{{~/if~}} + +{{~#if allOf~}} + {{~#each allOf~}} + {{~> ts_type ~}} + {{~#unless @last~}}&{{~/unless~}} + {{~/each~}} +{{~/if~}} + +{{~#if anyOf~}} + {{~#each anyOf~}} + {{~> ts_type ~}} + {{~#unless @last~}}|{{~/unless~}} + {{~/each~}} +{{~/if~}} + +{{~#if oneOf~}} + {{~#each oneOf~}} + {{~> ts_type ~}} + {{~#unless @last~}}|{{~/unless~}} + {{~/each~}} +{{~/if~}} + +{{#if (isUnknown .)}} +unknown +{{/if}} + +{{~#*inline "type_array"~}} + ({{~> ts_type items ~}})[] +{{~/inline~}} + +{{~#*inline "type_boolean"~}} + boolean +{{~/inline~}} + +{{~#*inline "type_integer"~}} + number +{{~/inline~}} + +{{~#*inline "type_number"~}} + number +{{~/inline~}} + +{{~#*inline "type_object"~}} + {{~#if (eq x-modify "required")}} Required< {{/if~}} + {{~#if (eq x-modify "partial")}} Partial< {{/if~}} + { + {{#each properties}} + {{#if description}} + /** + * {{{description}}} + */ + {{/if}} + '{{@key}}'{{~#unless (or (includes ../required @key) (defined default))}}?{{/unless~}}: {{> ts_type }}; + {{/each}} + {{~#if additionalProperties}} + {{~#if (eq additionalProperties true)~}} + [key: string]: unknown; + {{~else~}} + [key: string]: {{> ts_type additionalProperties}}; + {{~/if~}} + {{~/if~}} + } + {{~#if (eq x-modify "partial")}} > {{/if~}} + {{~#if (eq x-modify "required")}} > {{/if~}} +{{~/inline~}} + +{{~#*inline "type_string"~}} + {{~#if enum~}} + {{~#each enum~}} + '{{.}}' + {{~#unless @last~}}|{{~/unless~}} + {{~/each~}} + {{~else~}} + string + {{~/if~}} +{{~/inline~}} diff --git a/packages/kbn-openapi-generator/src/template_service/templates/zod_operation_schema.handlebars b/packages/kbn-openapi-generator/src/template_service/templates/zod_operation_schema.handlebars index 30bc647b1fb25..6e5d21363a5ae 100644 --- a/packages/kbn-openapi-generator/src/template_service/templates/zod_operation_schema.handlebars +++ b/packages/kbn-openapi-generator/src/template_service/templates/zod_operation_schema.handlebars @@ -7,8 +7,9 @@ {{> disclaimer}} -import { z } from "zod"; -import { requiredOptional, isValidDateMath, ArrayFromString, BooleanFromString } from "@kbn/zod-helpers" +import type { ZodTypeDef } from 'zod'; +import { z } from 'zod'; +import { requiredOptional, isValidDateMath, ArrayFromString, BooleanFromString } from '@kbn/zod-helpers'; {{#each imports}} import { @@ -25,8 +26,14 @@ import { {{/if}} */ {{/if}} +{{#if (isCircularSchema @key)}} +export type {{@key}} = {{> ts_type}}; +export type {{@key}}Input = {{> ts_input_type }}; +export const {{@key}}: z.ZodType<{{@key}}, ZodTypeDef, {{@key}}Input> = {{> zod_schema_item }}; +{{else}} export type {{@key}} = z.infer; export const {{@key}} = {{> zod_schema_item}}; +{{/if}} {{#if enum}} {{#unless (isSingle enum)}} export type {{@key}}Enum = typeof {{@key}}.enum; diff --git a/packages/kbn-openapi-generator/src/template_service/templates/zod_schema_item.handlebars b/packages/kbn-openapi-generator/src/template_service/templates/zod_schema_item.handlebars index 29d4453da4d7b..7ad0abaf1cad8 100644 --- a/packages/kbn-openapi-generator/src/template_service/templates/zod_schema_item.handlebars +++ b/packages/kbn-openapi-generator/src/template_service/templates/zod_schema_item.handlebars @@ -6,7 +6,11 @@ {{~/if~}} {{~#if $ref~}} - {{referenceName}} + {{~#if (isCircularRef $ref)~}} + z.lazy(() => {{referenceName}}) + {{~else~}} + {{referenceName}} + {{~/if~}} {{~#if nullable}}.nullable(){{/if~}} {{~#if (eq requiredBool false)}}.optional(){{/if~}} {{~#if (defined default)}}.default({{{toJSON default}}}){{/if~}} @@ -87,11 +91,7 @@ z.unknown() * {{{description}}} */ {{/if}} - {{#if (startsWithSpecialChar @key)}} - '{{@key}}': {{> zod_schema_item requiredBool=(includes ../required @key)}}, - {{else}} - {{@key}}: {{> zod_schema_item requiredBool=(includes ../required @key)}}, - {{/if}} + '{{@key}}':{{~> zod_schema_item requiredBool=(includes ../required @key)~}}, {{/each}} }) {{~#if (eq additionalProperties false)}}.strict(){{/if~}} @@ -127,4 +127,3 @@ z.unknown() {{~#if pattern}}.regex(/{{pattern}}/){{/if~}} {{~/if~}} {{~/inline~}} - From a021e48e2b236852dae5f9602e21b1c9de300ac0 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 18 Jun 2024 11:50:35 -0700 Subject: [PATCH 075/127] [OAS] Refresh connectors API document (#186141) --- .../plugins/actions/docs/openapi/bundled.json | 1700 ++++++++--------- .../plugins/actions/docs/openapi/bundled.yaml | 1174 ++++++------ .../docs/openapi/bundled_serverless.json | 388 ++-- .../docs/openapi/bundled_serverless.yaml | 300 ++- .../components/parameters/action_id.yaml | 3 +- .../components/parameters/connector_id.yaml | 3 +- .../components/parameters/space_id.yaml | 3 +- .../openapi/components/responses/400.yaml | 9 +- .../openapi/components/responses/401.yaml | 6 +- .../openapi/components/responses/404.yaml | 9 +- .../config_properties_cases_webhook.yaml | 21 +- .../schemas/config_properties_email.yaml | 15 +- .../schemas/config_properties_index.yaml | 5 +- .../schemas/config_properties_pagerduty.yaml | 8 +- .../schemas/config_properties_webhook.yaml | 7 +- .../schemas/config_properties_xmatters.yaml | 5 +- ...nnector_response_properties_serverlog.yaml | 5 +- .../components/schemas/connector_types.yaml | 3 +- .../create_connector_request_bedrock.yaml | 6 +- ...reate_connector_request_cases_webhook.yaml | 6 +- .../create_connector_request_d3security.yaml | 6 +- .../create_connector_request_email.yaml | 6 +- .../create_connector_request_gemini.yaml | 6 +- .../create_connector_request_genai.yaml | 6 +- .../create_connector_request_index.yaml | 6 +- .../create_connector_request_jira.yaml | 6 +- .../create_connector_request_opsgenie.yaml | 6 +- .../create_connector_request_pagerduty.yaml | 6 +- .../create_connector_request_resilient.yaml | 6 +- .../create_connector_request_sentinelone.yaml | 6 +- .../create_connector_request_serverlog.yaml | 6 +- .../create_connector_request_servicenow.yaml | 6 +- ...ate_connector_request_servicenow_itom.yaml | 6 +- ...eate_connector_request_servicenow_sir.yaml | 6 +- .../create_connector_request_slack_api.yaml | 6 +- ...reate_connector_request_slack_webhook.yaml | 6 +- .../create_connector_request_swimlane.yaml | 6 +- .../create_connector_request_teams.yaml | 6 +- .../create_connector_request_tines.yaml | 6 +- .../create_connector_request_torq.yaml | 6 +- .../create_connector_request_webhook.yaml | 6 +- .../create_connector_request_xmatters.yaml | 6 +- .../components/schemas/is_deprecated.yaml | 3 +- .../schemas/is_missing_secrets.yaml | 3 +- .../components/schemas/is_preconfigured.yaml | 3 +- .../components/schemas/is_system_action.yaml | 3 +- .../schemas/referenced_by_count.yaml | 3 +- ...un_connector_params_trigger_pagerduty.yaml | 9 +- ...run_connector_subaction_closeincident.yaml | 6 +- .../run_connector_subaction_createalert.yaml | 3 +- ...connector_subaction_fieldsbyissuetype.yaml | 3 +- .../run_connector_subaction_getincident.yaml | 3 +- .../run_connector_subaction_issue.yaml | 3 +- ...pdate_connector_request_cases_webhook.yaml | 3 +- .../update_connector_request_swimlane.yaml | 3 +- .../actions/docs/openapi/entrypoint.yaml | 23 +- .../docs/openapi/entrypoint_serverless.yaml | 7 +- .../openapi/paths/api@actions@connector.yaml | 2 +- .../api@actions@connector@{connectorid}.yaml | 11 +- ...ions@connector@{connectorid}@_execute.yaml | 2 +- .../paths/api@actions@connector_types.yaml | 23 +- .../openapi/paths/api@actions@connectors.yaml | 2 +- .../paths/s@{spaceid}@api@actions.yaml | 4 +- ...paceid}@api@actions@action@{actionid}.yaml | 6 +- ...pi@actions@action@{actionid}@_execute.yaml | 2 +- .../s@{spaceid}@api@actions@connector.yaml | 2 +- ...}@api@actions@connector@{connectorid}.yaml | 11 +- ...ions@connector@{connectorid}@_execute.yaml | 2 +- ...{spaceid}@api@actions@connector_types.yaml | 20 +- .../s@{spaceid}@api@actions@connectors.yaml | 2 +- ...paceid}@api@actions@list_action_types.yaml | 5 +- 71 files changed, 1656 insertions(+), 2324 deletions(-) diff --git a/x-pack/plugins/actions/docs/openapi/bundled.json b/x-pack/plugins/actions/docs/openapi/bundled.json index ae6e418dc775e..df93f77a5ab20 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.json +++ b/x-pack/plugins/actions/docs/openapi/bundled.json @@ -1,5 +1,5 @@ { - "openapi": "3.1.0", + "openapi": "3.0.3", "info": { "title": "Connectors", "description": "OpenAPI schema for Connectors endpoints", @@ -32,16 +32,20 @@ } ], "paths": { - "/api/actions/connector": { + "/s/{spaceId}/api/actions/connector": { "post": { - "summary": "Creates a connector.", - "operationId": "createConnector", + "summary": "Create a connector", + "operationId": "createConnectorWithSpaceId", + "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" ], "parameters": [ { "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -99,16 +103,20 @@ } } }, - "/api/actions/connector/{connectorId}": { + "/s/{spaceId}/api/actions/connector/{connectorId}": { "get": { - "summary": "Retrieves a connector by ID.", - "operationId": "getConnector", + "summary": "Get connector information", + "operationId": "getConnectorWithSpaceId", + "description": "You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" ], "parameters": [ { "$ref": "#/components/parameters/connector_id" + }, + { + "$ref": "#/components/parameters/space_id" } ], "responses": { @@ -136,8 +144,9 @@ } }, "delete": { - "summary": "Deletes a connector.", - "operationId": "deleteConnector", + "summary": "Delete a connector", + "operationId": "deleteConnectorWithSpaceId", + "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered.\n", "tags": [ "connectors" ], @@ -147,6 +156,9 @@ }, { "$ref": "#/components/parameters/connector_id" + }, + { + "$ref": "#/components/parameters/space_id" } ], "responses": { @@ -162,8 +174,9 @@ } }, "post": { - "summary": "Creates a connector.", - "operationId": "createConnectorId", + "summary": "Create a connector", + "operationId": "createConnectorIdWithSpaceId", + "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" ], @@ -171,16 +184,17 @@ { "$ref": "#/components/parameters/kbn_xsrf" }, + { + "$ref": "#/components/parameters/space_id" + }, { "in": "path", "name": "connectorId", - "description": "A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated.\n", + "description": "A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated.", "required": true, "schema": { "type": "string", - "examples": [ - "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" - ] + "example": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" } } ], @@ -221,8 +235,9 @@ } }, "put": { - "summary": "Updates the attributes for a connector.", - "operationId": "updateConnector", + "summary": "Update a connector", + "operationId": "updateConnectorWithSpaceId", + "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" ], @@ -232,6 +247,9 @@ }, { "$ref": "#/components/parameters/connector_id" + }, + { + "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -272,10 +290,138 @@ } } }, - "/api/actions/connector/{connectorId}/_execute": { + "/s/{spaceId}/api/actions/connectors": { + "get": { + "summary": "Get all connectors", + "operationId": "getConnectorsWithSpaceId", + "description": "You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/space_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/connector_response_properties" + } + }, + "examples": { + "getConnectorsResponse": { + "$ref": "#/components/examples/get_connectors_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + } + } + }, + "/s/{spaceId}/api/actions/connector_types": { + "get": { + "summary": "Get all connector types", + "operationId": "getConnectorTypesWithSpaceId", + "description": "You do not need any Kibana feature privileges to run this API.\n", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/space_id" + }, + { + "in": "query", + "name": "feature_id", + "description": "A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases).", + "schema": { + "$ref": "#/components/schemas/features" + } + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "title": "Get connector types response body properties", + "description": "The properties vary for each connector type.", + "type": "array", + "items": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in Kibana.", + "example": true + }, + "enabled_in_config": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in the Kibana `.yml` file.", + "example": true + }, + "enabled_in_license": { + "type": "boolean", + "description": "Indicates whether the connector is enabled in the license.", + "example": true + }, + "id": { + "$ref": "#/components/schemas/connector_types" + }, + "minimum_license_required": { + "type": "string", + "description": "The license that is required to use the connector type.", + "example": "basic" + }, + "name": { + "type": "string", + "description": "The name of the connector type.", + "example": "Index" + }, + "supported_feature_ids": { + "type": "array", + "description": "The Kibana features that are supported by the connector type.", + "items": { + "$ref": "#/components/schemas/features" + }, + "example": [ + "alerting", + "uptime", + "siem" + ] + } + } + } + }, + "examples": { + "getConnectorTypesResponse": { + "$ref": "#/components/examples/get_connector_types_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + } + } + }, + "/s/{spaceId}/api/actions/connector/{connectorId}/_execute": { "post": { - "summary": "Runs a connector.", - "operationId": "runConnector", + "summary": "Run a connector", + "operationId": "runConnectorWithSpaceId", "description": "You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges.\n", "tags": [ "connectors" @@ -286,6 +432,9 @@ }, { "$ref": "#/components/parameters/connector_id" + }, + { + "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -296,21 +445,12 @@ "$ref": "#/components/schemas/run_connector_request" }, "examples": { - "runCasesWebhookConnectorRequest": { - "$ref": "#/components/examples/run_cases_webhook_connector_request" - }, - "runEmailConnectorRequest": { - "$ref": "#/components/examples/run_email_connector_request" - }, "runIndexConnectorRequest": { "$ref": "#/components/examples/run_index_connector_request" }, "runJiraConnectorRequest": { "$ref": "#/components/examples/run_jira_connector_request" }, - "runPagerDutyConnectorRequest": { - "$ref": "#/components/examples/run_pagerduty_connector_request" - }, "runServerLogConnectorRequest": { "$ref": "#/components/examples/run_server_log_connector_request" }, @@ -359,6 +499,12 @@ } ] }, + "message": { + "type": "string" + }, + "service_message": { + "type": "string" + }, "status": { "type": "string", "description": "The status of the action.", @@ -370,21 +516,12 @@ } }, "examples": { - "runCasesWebhookConnectorResponse": { - "$ref": "#/components/examples/run_cases_webhook_connector_response" - }, - "runEmailConnectorResponse": { - "$ref": "#/components/examples/run_email_connector_response" - }, "runIndexConnectorResponse": { "$ref": "#/components/examples/run_index_connector_response" }, "runJiraConnectorResponse": { "$ref": "#/components/examples/run_jira_connector_response" }, - "runPagerDutyConnectorResponse": { - "$ref": "#/components/examples/run_pagerduty_connector_response" - }, "runServerLogConnectorResponse": { "$ref": "#/components/examples/run_server_log_connector_response" }, @@ -407,27 +544,62 @@ } } }, - "/api/actions/connectors": { - "get": { - "summary": "Retrieves all connectors.", - "operationId": "getConnectors", + "/api/actions/connector": { + "post": { + "summary": "Create a connector", + "operationId": "createConnector", "tags": [ "connectors" ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_connector_request" + }, + "examples": { + "createEmailConnectorRequest": { + "$ref": "#/components/examples/create_email_connector_request" + }, + "createIndexConnectorRequest": { + "$ref": "#/components/examples/create_index_connector_request" + }, + "createWebhookConnectorRequest": { + "$ref": "#/components/examples/create_webhook_connector_request" + }, + "createXmattersConnectorRequest": { + "$ref": "#/components/examples/create_xmatters_connector_request" + } + } + } + } + }, "responses": { "200": { "description": "Indicates a successful call.", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/connector_response_properties" - } + "$ref": "#/components/schemas/connector_response_properties" }, "examples": { - "getConnectorsResponse": { - "$ref": "#/components/examples/get_connectors_response" + "createEmailConnectorResponse": { + "$ref": "#/components/examples/create_email_connector_response" + }, + "createIndexConnectorResponse": { + "$ref": "#/components/examples/create_index_connector_response" + }, + "createWebhookConnectorResponse": { + "$ref": "#/components/examples/create_webhook_connector_response" + }, + "createXmattersConnectorResponse": { + "$ref": "#/components/examples/create_xmatters_connector_response" } } } @@ -439,195 +611,16 @@ } } }, - "/api/actions/connector_types": { + "/api/actions/connector/{connectorId}": { "get": { - "summary": "Retrieves a list of all connector types.", - "operationId": "getConnectorTypes", + "summary": "Get a connector information", + "operationId": "getConnector", "tags": [ "connectors" ], "parameters": [ { - "in": "query", - "name": "feature_id", - "description": "A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases).", - "schema": { - "$ref": "#/components/schemas/features" - } - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "title": "Get connector types response body properties", - "description": "The properties vary for each connector type.", - "type": "array", - "items": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Indicates whether the connector type is enabled in Kibana.", - "examples": [ - true - ] - }, - "enabled_in_config": { - "type": "boolean", - "description": "Indicates whether the connector type is enabled in the Kibana configuration file.", - "examples": [ - true - ] - }, - "enabled_in_license": { - "type": "boolean", - "description": "Indicates whether the connector is enabled in the license.", - "examples": [ - true - ] - }, - "id": { - "$ref": "#/components/schemas/connector_types" - }, - "is_system_action_type": { - "type": "boolean", - "examples": [ - false - ] - }, - "minimum_license_required": { - "type": "string", - "description": "The license that is required to use the connector type.", - "examples": [ - "basic" - ] - }, - "name": { - "type": "string", - "description": "The name of the connector type.", - "examples": [ - "Index" - ] - }, - "supported_feature_ids": { - "type": "array", - "description": "The features that are supported by the connector type.", - "items": { - "$ref": "#/components/schemas/features" - }, - "examples": [ - [ - "alerting", - "cases", - "siem" - ] - ] - } - } - } - }, - "examples": { - "getConnectorTypesServerlessResponse": { - "$ref": "#/components/examples/get_connector_types_generativeai_response" - } - } - } - } - }, - "401": { - "$ref": "#/components/responses/401" - } - } - } - }, - "/s/{spaceId}/api/actions/connector": { - "post": { - "summary": "Creates a connector.", - "operationId": "createConnectorWithSpaceId", - "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", - "tags": [ - "connectors" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "$ref": "#/components/parameters/space_id" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/create_connector_request" - }, - "examples": { - "createEmailConnectorRequest": { - "$ref": "#/components/examples/create_email_connector_request" - }, - "createIndexConnectorRequest": { - "$ref": "#/components/examples/create_index_connector_request" - }, - "createWebhookConnectorRequest": { - "$ref": "#/components/examples/create_webhook_connector_request" - }, - "createXmattersConnectorRequest": { - "$ref": "#/components/examples/create_xmatters_connector_request" - } - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/connector_response_properties" - }, - "examples": { - "createEmailConnectorResponse": { - "$ref": "#/components/examples/create_email_connector_response" - }, - "createIndexConnectorResponse": { - "$ref": "#/components/examples/create_index_connector_response" - }, - "createWebhookConnectorResponse": { - "$ref": "#/components/examples/create_webhook_connector_response" - }, - "createXmattersConnectorResponse": { - "$ref": "#/components/examples/create_xmatters_connector_response" - } - } - } - } - }, - "401": { - "$ref": "#/components/responses/401" - } - } - } - }, - "/s/{spaceId}/api/actions/connector/{connectorId}": { - "get": { - "summary": "Retrieves a connector by ID.", - "operationId": "getConnectorWithSpaceId", - "description": "You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", - "tags": [ - "connectors" - ], - "parameters": [ - { - "$ref": "#/components/parameters/connector_id" - }, - { - "$ref": "#/components/parameters/space_id" + "$ref": "#/components/parameters/connector_id" } ], "responses": { @@ -655,9 +648,8 @@ } }, "delete": { - "summary": "Deletes a connector.", - "operationId": "deleteConnectorWithSpaceId", - "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered.\n", + "summary": "Delete a connector", + "operationId": "deleteConnector", "tags": [ "connectors" ], @@ -667,9 +659,6 @@ }, { "$ref": "#/components/parameters/connector_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "responses": { @@ -685,9 +674,8 @@ } }, "post": { - "summary": "Creates a connector.", - "operationId": "createConnectorIdWithSpaceId", - "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", + "summary": "Create a connector", + "operationId": "createConnectorId", "tags": [ "connectors" ], @@ -695,19 +683,14 @@ { "$ref": "#/components/parameters/kbn_xsrf" }, - { - "$ref": "#/components/parameters/space_id" - }, { "in": "path", "name": "connectorId", - "description": "A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated.", + "description": "A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated.\n", "required": true, "schema": { "type": "string", - "examples": [ - "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" - ] + "example": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" } } ], @@ -748,9 +731,8 @@ } }, "put": { - "summary": "Updates the attributes for a connector.", - "operationId": "updateConnectorWithSpaceId", - "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", + "summary": "Update a connector", + "operationId": "updateConnector", "tags": [ "connectors" ], @@ -760,9 +742,6 @@ }, { "$ref": "#/components/parameters/connector_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -803,150 +782,10 @@ } } }, - "/s/{spaceId}/api/actions/connectors": { - "get": { - "summary": "Retrieves all connectors.", - "operationId": "getConnectorsWithSpaceId", - "description": "You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", - "tags": [ - "connectors" - ], - "parameters": [ - { - "$ref": "#/components/parameters/space_id" - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/connector_response_properties" - } - }, - "examples": { - "getConnectorsResponse": { - "$ref": "#/components/examples/get_connectors_response" - } - } - } - } - }, - "401": { - "$ref": "#/components/responses/401" - } - } - } - }, - "/s/{spaceId}/api/actions/connector_types": { - "get": { - "summary": "Retrieves a list of all connector types.", - "operationId": "getConnectorTypesWithSpaceId", - "description": "You do not need any Kibana feature privileges to run this API.\n", - "tags": [ - "connectors" - ], - "parameters": [ - { - "$ref": "#/components/parameters/space_id" - }, - { - "in": "query", - "name": "feature_id", - "description": "A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases).", - "schema": { - "$ref": "#/components/schemas/features" - } - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "title": "Get connector types response body properties", - "description": "The properties vary for each connector type.", - "type": "array", - "items": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Indicates whether the connector type is enabled in Kibana.", - "examples": [ - true - ] - }, - "enabled_in_config": { - "type": "boolean", - "description": "Indicates whether the connector type is enabled in the Kibana `.yml` file.", - "examples": [ - true - ] - }, - "enabled_in_license": { - "type": "boolean", - "description": "Indicates whether the connector is enabled in the license.", - "examples": [ - true - ] - }, - "id": { - "$ref": "#/components/schemas/connector_types" - }, - "minimum_license_required": { - "type": "string", - "description": "The license that is required to use the connector type.", - "examples": [ - "basic" - ] - }, - "name": { - "type": "string", - "description": "The name of the connector type.", - "examples": [ - "Index" - ] - }, - "supported_feature_ids": { - "type": "array", - "description": "The Kibana features that are supported by the connector type.", - "items": { - "$ref": "#/components/schemas/features" - }, - "examples": [ - [ - "alerting", - "uptime", - "siem" - ] - ] - } - } - } - }, - "examples": { - "getConnectorTypesResponse": { - "$ref": "#/components/examples/get_connector_types_response" - } - } - } - } - }, - "401": { - "$ref": "#/components/responses/401" - } - } - } - }, - "/s/{spaceId}/api/actions/connector/{connectorId}/_execute": { + "/api/actions/connector/{connectorId}/_execute": { "post": { - "summary": "Runs a connector.", - "operationId": "runConnectorWithSpaceId", + "summary": "Run a connector", + "operationId": "runConnector", "description": "You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges.\n", "tags": [ "connectors" @@ -957,9 +796,6 @@ }, { "$ref": "#/components/parameters/connector_id" - }, - { - "$ref": "#/components/parameters/space_id" } ], "requestBody": { @@ -970,12 +806,21 @@ "$ref": "#/components/schemas/run_connector_request" }, "examples": { + "runCasesWebhookConnectorRequest": { + "$ref": "#/components/examples/run_cases_webhook_connector_request" + }, + "runEmailConnectorRequest": { + "$ref": "#/components/examples/run_email_connector_request" + }, "runIndexConnectorRequest": { "$ref": "#/components/examples/run_index_connector_request" }, "runJiraConnectorRequest": { "$ref": "#/components/examples/run_jira_connector_request" }, + "runPagerDutyConnectorRequest": { + "$ref": "#/components/examples/run_pagerduty_connector_request" + }, "runServerLogConnectorRequest": { "$ref": "#/components/examples/run_server_log_connector_request" }, @@ -1024,12 +869,6 @@ } ] }, - "message": { - "type": "string" - }, - "service_message": { - "type": "string" - }, "status": { "type": "string", "description": "The status of the action.", @@ -1041,12 +880,21 @@ } }, "examples": { + "runCasesWebhookConnectorResponse": { + "$ref": "#/components/examples/run_cases_webhook_connector_response" + }, + "runEmailConnectorResponse": { + "$ref": "#/components/examples/run_email_connector_response" + }, "runIndexConnectorResponse": { "$ref": "#/components/examples/run_index_connector_response" }, "runJiraConnectorResponse": { "$ref": "#/components/examples/run_jira_connector_response" }, + "runPagerDutyConnectorResponse": { + "$ref": "#/components/examples/run_pagerduty_connector_response" + }, "runServerLogConnectorResponse": { "$ref": "#/components/examples/run_server_log_connector_response" }, @@ -1069,9 +917,131 @@ } } }, + "/api/actions/connectors": { + "get": { + "summary": "Get all connectors", + "operationId": "getConnectors", + "tags": [ + "connectors" + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/connector_response_properties" + } + }, + "examples": { + "getConnectorsResponse": { + "$ref": "#/components/examples/get_connectors_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + } + } + }, + "/api/actions/connector_types": { + "get": { + "summary": "Get all connector types", + "operationId": "getConnectorTypes", + "tags": [ + "connectors" + ], + "parameters": [ + { + "in": "query", + "name": "feature_id", + "description": "A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases).", + "schema": { + "$ref": "#/components/schemas/features" + } + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "title": "Get connector types response body properties", + "description": "The properties vary for each connector type.", + "type": "array", + "items": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in Kibana.", + "example": true + }, + "enabled_in_config": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in the Kibana configuration file.", + "example": true + }, + "enabled_in_license": { + "type": "boolean", + "description": "Indicates whether the connector is enabled in the license.", + "example": true + }, + "id": { + "$ref": "#/components/schemas/connector_types" + }, + "is_system_action_type": { + "type": "boolean", + "example": false + }, + "minimum_license_required": { + "type": "string", + "description": "The license that is required to use the connector type.", + "example": "basic" + }, + "name": { + "type": "string", + "description": "The name of the connector type.", + "example": "Index" + }, + "supported_feature_ids": { + "type": "array", + "description": "The features that are supported by the connector type.", + "items": { + "$ref": "#/components/schemas/features" + }, + "example": [ + "alerting", + "cases", + "siem" + ] + } + } + } + }, + "examples": { + "getConnectorTypesServerlessResponse": { + "$ref": "#/components/examples/get_connector_types_generativeai_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + } + } + }, "/s/{spaceId}/api/actions/action/{actionId}": { "delete": { - "summary": "Deletes a connector.", + "summary": "Delete a connector", "operationId": "legacyDeleteConnector", "deprecated": true, "description": "Deprecated in 7.13.0. Use the delete connector API instead. WARNING: When you delete a connector, it cannot be recovered.\n", @@ -1099,7 +1069,7 @@ } }, "get": { - "summary": "Retrieves a connector by ID.", + "summary": "Get connector information", "operationId": "legacyGetConnector", "description": "Deprecated in 7.13.0. Use the get connector API instead.", "deprecated": true, @@ -1124,7 +1094,7 @@ } }, "put": { - "summary": "Updates the attributes for a connector.", + "summary": "Update a connector", "operationId": "legacyUpdateConnector", "deprecated": true, "description": "Deprecated in 7.13.0. Use the update connector API instead.", @@ -1180,7 +1150,7 @@ }, "/s/{spaceId}/api/actions": { "get": { - "summary": "Retrieves all connectors.", + "summary": "Get all connectors", "operationId": "legacyGetConnectors", "deprecated": true, "description": "Deprecated in 7.13.0. Use the get all connectors API instead.", @@ -1212,7 +1182,7 @@ } }, "post": { - "summary": "Creates a connector.", + "summary": "Create a connector", "operationId": "legacyCreateConnector", "deprecated": true, "description": "Deprecated in 7.13.0. Use the create connector API instead.", @@ -1268,7 +1238,7 @@ }, "/s/{spaceId}/api/actions/list_action_types": { "get": { - "summary": "Retrieves a list of all connector types.", + "summary": "Get connector types", "operationId": "legacyGetConnectorTypes", "deprecated": true, "description": "Deprecated in 7.13.0. Use the get all connector types API instead.", @@ -1303,9 +1273,7 @@ "enabledInLicense": { "type": "boolean", "description": "Indicates whether the connector is enabled in the license.", - "examples": [ - true - ] + "example": true }, "id": { "type": "string", @@ -1333,7 +1301,7 @@ }, "/s/{spaceId}/api/actions/action/{actionId}/_execute": { "post": { - "summary": "Runs a connector.", + "summary": "Run a connector", "operationId": "legacyRunConnector", "deprecated": true, "description": "Deprecated in 7.13.0. Use the run connector API instead.", @@ -1438,28 +1406,24 @@ "description": "Cross-site request forgery protection", "required": true }, - "connector_id": { + "space_id": { "in": "path", - "name": "connectorId", - "description": "An identifier for the connector.", + "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", - "examples": [ - "df770e30-8b8b-11ed-a780-3b746c987a81" - ] + "example": "default" } }, - "space_id": { + "connector_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.", + "name": "connectorId", + "description": "An identifier for the connector.", "required": true, "schema": { "type": "string", - "examples": [ - "default" - ] + "example": "df770e30-8b8b-11ed-a780-3b746c987a81" } }, "action_id": { @@ -1469,9 +1433,7 @@ "required": true, "schema": { "type": "string", - "examples": [ - "c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad" - ] + "example": "c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad" } } }, @@ -1496,16 +1458,12 @@ "enum": [ ".bedrock" ], - "examples": [ - ".bedrock" - ] + "example": ".bedrock" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_bedrock" @@ -1532,16 +1490,12 @@ "enum": [ ".gemini" ], - "examples": [ - ".gemini" - ] + "example": ".gemini" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_gemini" @@ -1567,16 +1521,12 @@ "enum": [ ".cases-webhook" ], - "examples": [ - ".cases-webhook" - ] + "example": ".cases-webhook" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_cases_webhook" @@ -1603,16 +1553,12 @@ "enum": [ ".d3security" ], - "examples": [ - ".d3security" - ] + "example": ".d3security" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_d3security" @@ -1639,16 +1585,12 @@ "enum": [ ".email" ], - "examples": [ - ".email" - ] + "example": ".email" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_email" @@ -1675,16 +1617,12 @@ "enum": [ ".gen-ai" ], - "examples": [ - ".gen-ai" - ] + "example": ".gen-ai" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_genai" @@ -1710,16 +1648,12 @@ "enum": [ ".index" ], - "examples": [ - ".index" - ] + "example": ".index" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" } } }, @@ -1743,16 +1677,12 @@ "enum": [ ".jira" ], - "examples": [ - ".jira" - ] + "example": ".jira" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_jira" @@ -1779,16 +1709,12 @@ "enum": [ ".opsgenie" ], - "examples": [ - ".opsgenie" - ] + "example": ".opsgenie" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_opsgenie" @@ -1815,16 +1741,12 @@ "enum": [ ".pagerduty" ], - "examples": [ - ".pagerduty" - ] + "example": ".pagerduty" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_pagerduty" @@ -1848,9 +1770,7 @@ "connector_type_id": { "description": "The type of connector.", "type": "string", - "examples": [ - ".resilient" - ], + "example": ".resilient", "enum": [ ".resilient" ] @@ -1858,9 +1778,7 @@ "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_resilient" @@ -1888,16 +1806,12 @@ "enum": [ ".sentinelone" ], - "examples": [ - ".sentinelone" - ] + "example": ".sentinelone" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_sentinelone" @@ -1919,16 +1833,12 @@ "enum": [ ".server-log" ], - "examples": [ - ".server-log" - ] + "example": ".server-log" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" } } }, @@ -1952,16 +1862,12 @@ "enum": [ ".servicenow" ], - "examples": [ - ".servicenow" - ] + "example": ".servicenow" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_servicenow" @@ -1988,16 +1894,12 @@ "enum": [ ".servicenow-itom" ], - "examples": [ - ".servicenow-itom" - ] + "example": ".servicenow-itom" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_servicenow" @@ -2024,16 +1926,12 @@ "enum": [ ".servicenow-sir" ], - "examples": [ - ".servicenow-sir" - ] + "example": ".servicenow-sir" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_servicenow" @@ -2059,16 +1957,12 @@ "enum": [ ".slack_api" ], - "examples": [ - ".slack_api" - ] + "example": ".slack_api" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_slack_api" @@ -2091,16 +1985,12 @@ "enum": [ ".slack" ], - "examples": [ - ".slack" - ] + "example": ".slack" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_slack_webhook" @@ -2127,16 +2017,12 @@ "enum": [ ".swimlane" ], - "examples": [ - ".swimlane" - ] + "example": ".swimlane" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_swimlane" @@ -2159,16 +2045,12 @@ "enum": [ ".teams" ], - "examples": [ - ".teams" - ] + "example": ".teams" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_teams" @@ -2195,16 +2077,12 @@ "enum": [ ".tines" ], - "examples": [ - ".tines" - ] + "example": ".tines" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_tines" @@ -2231,16 +2109,12 @@ "enum": [ ".torq" ], - "examples": [ - ".torq" - ] + "example": ".torq" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_torq" @@ -2267,16 +2141,12 @@ "enum": [ ".webhook" ], - "examples": [ - ".webhook" - ] + "example": ".webhook" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_webhook" @@ -2303,16 +2173,12 @@ "enum": [ ".xmatters" ], - "examples": [ - ".xmatters" - ] + "example": ".xmatters" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_xmatters" @@ -2418,9 +2284,7 @@ "createCommentJson": { "type": "string", "description": "A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is `case.comment`. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.\n", - "examples": [ - "{\"body\": {{{case.comment}}}}" - ] + "example": "{\"body\": {{{case.comment}}}}" }, "createCommentMethod": { "type": "string", @@ -2435,16 +2299,12 @@ "createCommentUrl": { "type": "string", "description": "The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts.\n", - "examples": [ - "https://example.com/issue/{{{external.system.id}}}/comment" - ] + "example": "https://example.com/issue/{{{external.system.id}}}/comment" }, "createIncidentJson": { "type": "string", "description": "A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.\n", - "examples": [ - "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" - ] + "example": "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" }, "createIncidentMethod": { "type": "string", @@ -2471,9 +2331,7 @@ "getIncidentUrl": { "type": "string", "description": "The REST API URL to get the case by ID from the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.\n", - "examples": [ - "https://example.com/issue/{{{external.system.id}}}" - ] + "example": "https://example.com/issue/{{{external.system.id}}}" }, "hasAuth": { "type": "boolean", @@ -2487,9 +2345,7 @@ "updateIncidentJson": { "type": "string", "description": "The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.\n", - "examples": [ - "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" - ] + "example": "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" }, "updateIncidentMethod": { "type": "string", @@ -2504,16 +2360,12 @@ "updateIncidentUrl": { "type": "string", "description": "The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n", - "examples": [ - "https://example.com/issue/{{{external.system.ID}}}" - ] + "example": "https://example.com/issue/{{{external.system.ID}}}" }, "viewIncidentUrl": { "type": "string", "description": "The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL.\n", - "examples": [ - "https://testing-jira.atlassian.net/browse/{{{external.system.title}}}" - ] + "example": "https://testing-jira.atlassian.net/browse/{{{external.system.title}}}" } } }, @@ -2569,10 +2421,8 @@ "properties": { "clientId": { "description": "The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required.\n", - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "from": { "description": "The from address for all emails sent by the connector. It must be specified in `user@host-name` format.\n", @@ -2588,10 +2438,8 @@ "type": "string" }, "oauthTokenUrl": { - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "port": { "description": "The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. \n", @@ -2615,10 +2463,8 @@ }, "tenantId": { "description": "The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required.\n", - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true } } }, @@ -2730,10 +2576,8 @@ "executionTimeField": { "description": "A field that indicates when the document was indexed.", "default": null, - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "index": { "description": "The Elasticsearch index to be written to.", @@ -2819,13 +2663,9 @@ "properties": { "apiUrl": { "description": "The PagerDuty event URL.", - "type": [ - "string", - "null" - ], - "examples": [ - "https://events.pagerduty.com/v2/enqueue" - ] + "type": "string", + "nullable": true, + "example": "https://events.pagerduty.com/v2/enqueue" } } }, @@ -3395,10 +3235,10 @@ "properties": { "authType": { "type": "string", + "nullable": true, "enum": [ "webhook-authentication-basic", - "webhook-authentication-ssl", - "null" + "webhook-authentication-ssl" ], "description": "The type of authentication to use: basic, SSL, or none.\n" }, @@ -3419,10 +3259,8 @@ "description": "If `true`, a user name and password must be provided for login type authentication.\n" }, "headers": { - "type": [ - "object", - "null" - ], + "type": "object", + "nullable": true, "description": "A set of key-value pairs sent as headers with the request." }, "method": { @@ -3484,10 +3322,8 @@ "properties": { "configUrl": { "description": "The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`.\n", - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "usesBasic": { "description": "Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`).", @@ -4184,10 +4020,8 @@ ], "properties": { "config": { - "type": [ - "object", - "null" - ] + "type": "object", + "nullable": true }, "connector_type_id": { "type": "string", @@ -4727,37 +4561,27 @@ "is_deprecated": { "type": "boolean", "description": "Indicates whether the connector type is deprecated.", - "examples": [ - false - ] + "example": false }, "is_missing_secrets": { "type": "boolean", "description": "Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.", - "examples": [ - false - ] + "example": false }, "is_preconfigured": { "type": "boolean", "description": "Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. \n", - "examples": [ - false - ] + "example": false }, "is_system_action": { "type": "boolean", "description": "Indicates whether the connector is used for system actions.", - "examples": [ - false - ] + "example": false }, "referenced_by_count": { "type": "integer", "description": "Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API.\n", - "examples": [ - 2 - ] + "example": 2 }, "connector_response_properties": { "title": "Connector response properties", @@ -4920,9 +4744,7 @@ "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_cases_webhook" @@ -5199,9 +5021,7 @@ "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_swimlane" @@ -5384,6 +5204,51 @@ } ] }, + "features": { + "type": "string", + "description": "The feature that uses the connector.\n", + "enum": [ + "alerting", + "cases", + "generativeAIForSecurity", + "generativeAIForObservability", + "generativeAIForSearchPlayground", + "siem", + "uptime" + ] + }, + "connector_types": { + "title": "Connector types", + "type": "string", + "description": "The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`.", + "enum": [ + ".bedrock", + ".gemini", + ".cases-webhook", + ".d3security", + ".email", + ".gen-ai", + ".index", + ".jira", + ".opsgenie", + ".pagerduty", + ".resilient", + ".sentinelone", + ".servicenow", + ".servicenow-itom", + ".servicenow-sir", + ".server-log", + ".slack", + ".slack_api", + ".swimlane", + ".teams", + ".tines", + ".torq", + ".webhook", + ".xmatters" + ], + "example": ".server-log" + }, "run_connector_params_acknowledge_resolve_pagerduty": { "title": "PagerDuty connector parameters", "description": "Test an action that acknowledges or resolves a PagerDuty alert.", @@ -5537,16 +5402,12 @@ "class": { "description": "The class or type of the event.", "type": "string", - "examples": [ - "cpu load" - ] + "example": "cpu load" }, "component": { "description": "The component of the source machine that is responsible for the event.", "type": "string", - "examples": [ - "eth0" - ] + "example": "eth0" }, "customDetails": { "description": "Additional details to add to the event.", @@ -5567,9 +5428,7 @@ "group": { "description": "The logical grouping of components of a service.", "type": "string", - "examples": [ - "app-stack" - ] + "example": "app-stack" }, "links": { "description": "A list of links to add to the event.", @@ -5762,19 +5621,15 @@ ], "properties": { "correlation_id": { - "type": [ - "null", - "string" - ], + "type": "string", + "nullable": true, "description": "An identifier that is assigned to the incident when it is created by the connector. NOTE: If you use the default value and the rule generates multiple alerts that use the same alert IDs, the latest open incident for this correlation ID is closed unless you specify the external ID.\n", "maxLength": 100, "default": "{{rule.id}}:{{alert.id}}" }, "externalId": { - "type": [ - "null", - "string" - ], + "type": "string", + "nullable": true, "description": "The unique identifier (`incidentId`) for the incident in ServiceNow." } } @@ -5824,12 +5679,10 @@ "type": "object", "description": "The custom properties of the alert.", "additionalProperties": true, - "examples": [ - { - "key1": "value1", - "key2": "value2" - } - ] + "example": { + "key1": "value1", + "key2": "value2" + } }, "entity": { "type": "string", @@ -5961,9 +5814,7 @@ "id": { "type": "string", "description": "The Jira issue type identifier.", - "examples": [ - 10024 - ] + "example": 10024 } } } @@ -6045,9 +5896,7 @@ "externalId": { "type": "string", "description": "The Jira, ServiceNow ITSM, or ServiceNow SecOps issue identifier.", - "examples": [ - 71778 - ] + "example": 71778 } } } @@ -6077,9 +5926,7 @@ "id": { "type": "string", "description": "The Jira issue identifier.", - "examples": [ - 71778 - ] + "example": 71778 } } } @@ -6514,53 +6361,6 @@ } } }, - "features": { - "type": "string", - "description": "The feature that uses the connector.\n", - "enum": [ - "alerting", - "cases", - "generativeAIForSecurity", - "generativeAIForObservability", - "generativeAIForSearchPlayground", - "siem", - "uptime" - ] - }, - "connector_types": { - "title": "Connector types", - "type": "string", - "description": "The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`.", - "enum": [ - ".bedrock", - ".gemini", - ".cases-webhook", - ".d3security", - ".email", - ".gen-ai", - ".index", - ".jira", - ".opsgenie", - ".pagerduty", - ".resilient", - ".sentinelone", - ".servicenow", - ".servicenow-itom", - ".servicenow-sir", - ".server-log", - ".slack", - ".slack_api", - ".swimlane", - ".teams", - ".tines", - ".torq", - ".webhook", - ".xmatters" - ], - "examples": [ - ".server-log" - ] - }, "action_response_properties": { "title": "Action response properties", "description": "The properties vary depending on the action type.", @@ -6753,51 +6553,77 @@ } } }, - "run_cases_webhook_connector_request": { - "summary": "Run a Webhook - Case Management connector to create a case.", - "value": { - "params": { - "subAction": "pushToService", - "subActionParams": { - "comments": [ - { - "commentId": 1, - "comment": "A comment about the incident." - } - ], - "incident": { - "title": "Case title", - "description": "Description of the incident.", - "tags": [ - "tag1", - "tag2" - ], - "severity": "low", - "status": "open", - "id": "caseID" - } - } + "get_connectors_response": { + "summary": "A list of connectors", + "value": [ + { + "id": "preconfigured-email-connector", + "name": "my-preconfigured-email-notification", + "connector_type_id": ".email", + "is_preconfigured": true, + "is_deprecated": false, + "referenced_by_count": 0, + "is_system_action": false + }, + { + "id": "e07d0c80-8b8b-11ed-a780-3b746c987a81", + "name": "my-index-connector", + "config": { + "index": "test-index", + "refresh": false, + "executionTimeField": null + }, + "connector_type_id": ".index", + "is_preconfigured": false, + "is_deprecated": false, + "referenced_by_count": 2, + "is_missing_secrets": false, + "is_system_action": false } - } + ] }, - "run_email_connector_request": { - "summary": "Send an email message from an email connector.", - "value": { - "params": { - "bcc": [ - "user1@example.com" - ], - "cc": [ - "user2@example.com", - "user3@example.com" - ], - "message": "Test email message.", - "subject": "Test message subject", - "to": [ - "user4@example.com" + "get_connector_types_response": { + "summary": "A list of connector types", + "value": [ + { + "id": ".swimlane", + "name": "Swimlane", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "gold", + "supported_feature_ids": [ + "alerting", + "cases", + "siem" + ] + }, + { + "id": ".index", + "name": "Index", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "basic", + "supported_feature_ids": [ + "alerting", + "uptime", + "siem" + ] + }, + { + "id": ".server-log", + "name": "Server log", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "basic", + "supported_feature_ids": [ + "alerting", + "uptime" ] } - } + ] }, "run_index_connector_request": { "summary": "Run an index connector.", @@ -6821,24 +6647,6 @@ } } }, - "run_pagerduty_connector_request": { - "summary": "Run a PagerDuty connector to trigger an alert.", - "value": { - "params": { - "eventAction": "trigger", - "summary": "A brief event summary", - "links": [ - { - "href": "http://example.com/pagerduty", - "text": "An example link" - } - ], - "customDetails": { - "my_data_1": "test data" - } - } - } - }, "run_server_log_connector_request": { "summary": "Run a server log connector.", "value": { @@ -6875,75 +6683,26 @@ } } } - }, - "run_swimlane_connector_request": { - "summary": "Run a Swimlane connector to create an incident.", - "value": { - "params": { - "subAction": "pushToService", - "subActionParams": { - "comments": [ - { - "commentId": 1, - "comment": "A comment about the incident." - } - ], - "incident": { - "caseId": "1000", - "caseName": "Case name", - "description": "Description of the incident." - } - } - } - } - }, - "run_cases_webhook_connector_response": { - "summary": "Response from a pushToService action for a Webhook - Case Management connector.", - "value": { - "connector_id": "1824b5b8-c005-4dcc-adac-57f92db46459", - "data": { - "id": 100665, - "title": "TEST-29034", - "url": "https://example.com/browse/TEST-29034", - "pushedDate": "2023-12-05T19:43:36.360Z", - "comments": [ - { - "commentId": 1, - "pushedDate": "2023-12-05T19:43:36.360Z" - } - ] - }, - "status": "ok" - } - }, - "run_email_connector_response": { - "summary": "Response for sending a message from an email connector.", + }, + "run_swimlane_connector_request": { + "summary": "Run a Swimlane connector to create an incident.", "value": { - "connector_id": "7fc7b9a0-ecc9-11ec-8736-e7d63118c907", - "data": { - "accepted": [ - "user1@example.com", - "user2@example.com", - "user3@example.com", - "user4@example.com" - ], - "envelope": { - "from": "tester@example.com", - "to": [ - "user1@example.com", - "user2@example.com", - "user3@example.com", - "user4@example.com" - ] - }, - "envelopeTime": 8, - "messageTime": 3, - "messageSize": 729, - "response": "250 Message queued as QzEXKcGJ", - "messageId": "<08a92d29-642a-0706-750c-de5996bd5cf3@example.com>", - "rejected": [] - }, - "status": "ok" + "params": { + "subAction": "pushToService", + "subActionParams": { + "comments": [ + { + "commentId": 1, + "comment": "A comment about the incident." + } + ], + "incident": { + "caseId": "1000", + "caseName": "Case name", + "description": "Description of the incident." + } + } + } } }, "run_index_connector_response": { @@ -7008,18 +6767,6 @@ "status": "ok" } }, - "run_pagerduty_connector_response": { - "summary": "Response from running a PagerDuty connector.", - "value": { - "connector_id": "45de9f70-954f-4608-b12a-db7cf808e49d", - "data": { - "dedup_key": "5115e138b26b484a81eaea779faa6016", - "message": "Event processed", - "status": "success" - }, - "status": "ok" - } - }, "run_server_log_connector_response": { "summary": "Response from running a server log connector.", "value": { @@ -7158,34 +6905,130 @@ "status": "ok" } }, - "get_connectors_response": { - "summary": "A list of connectors", - "value": [ - { - "id": "preconfigured-email-connector", - "name": "my-preconfigured-email-notification", - "connector_type_id": ".email", - "is_preconfigured": true, - "is_deprecated": false, - "referenced_by_count": 0, - "is_system_action": false + "run_cases_webhook_connector_request": { + "summary": "Run a Webhook - Case Management connector to create a case.", + "value": { + "params": { + "subAction": "pushToService", + "subActionParams": { + "comments": [ + { + "commentId": 1, + "comment": "A comment about the incident." + } + ], + "incident": { + "title": "Case title", + "description": "Description of the incident.", + "tags": [ + "tag1", + "tag2" + ], + "severity": "low", + "status": "open", + "id": "caseID" + } + } + } + } + }, + "run_email_connector_request": { + "summary": "Send an email message from an email connector.", + "value": { + "params": { + "bcc": [ + "user1@example.com" + ], + "cc": [ + "user2@example.com", + "user3@example.com" + ], + "message": "Test email message.", + "subject": "Test message subject", + "to": [ + "user4@example.com" + ] + } + } + }, + "run_pagerduty_connector_request": { + "summary": "Run a PagerDuty connector to trigger an alert.", + "value": { + "params": { + "eventAction": "trigger", + "summary": "A brief event summary", + "links": [ + { + "href": "http://example.com/pagerduty", + "text": "An example link" + } + ], + "customDetails": { + "my_data_1": "test data" + } + } + } + }, + "run_cases_webhook_connector_response": { + "summary": "Response from a pushToService action for a Webhook - Case Management connector.", + "value": { + "connector_id": "1824b5b8-c005-4dcc-adac-57f92db46459", + "data": { + "id": 100665, + "title": "TEST-29034", + "url": "https://example.com/browse/TEST-29034", + "pushedDate": "2023-12-05T19:43:36.360Z", + "comments": [ + { + "commentId": 1, + "pushedDate": "2023-12-05T19:43:36.360Z" + } + ] }, - { - "id": "e07d0c80-8b8b-11ed-a780-3b746c987a81", - "name": "my-index-connector", - "config": { - "index": "test-index", - "refresh": false, - "executionTimeField": null + "status": "ok" + } + }, + "run_email_connector_response": { + "summary": "Response for sending a message from an email connector.", + "value": { + "connector_id": "7fc7b9a0-ecc9-11ec-8736-e7d63118c907", + "data": { + "accepted": [ + "user1@example.com", + "user2@example.com", + "user3@example.com", + "user4@example.com" + ], + "envelope": { + "from": "tester@example.com", + "to": [ + "user1@example.com", + "user2@example.com", + "user3@example.com", + "user4@example.com" + ] }, - "connector_type_id": ".index", - "is_preconfigured": false, - "is_deprecated": false, - "referenced_by_count": 2, - "is_missing_secrets": false, - "is_system_action": false - } - ] + "envelopeTime": 8, + "messageTime": 3, + "messageSize": 729, + "response": "250 Message queued as QzEXKcGJ", + "messageId": "<08a92d29-642a-0706-750c-de5996bd5cf3@example.com>", + "rejected": [] + }, + "status": "ok" + } + }, + "run_pagerduty_connector_response": { + "summary": "Response from running a PagerDuty connector.", + "value": { + "connector_id": "45de9f70-954f-4608-b12a-db7cf808e49d", + "data": { + "dedup_key": "5115e138b26b484a81eaea779faa6016", + "message": "Event processed", + "status": "success" + }, + "status": "ok" + } }, "get_connector_types_generativeai_response": { "summary": "A list of connector types for the `generativeAI` feature.", @@ -7231,49 +7074,6 @@ "is_system_action_type": false } ] - }, - "get_connector_types_response": { - "summary": "A list of connector types", - "value": [ - { - "id": ".swimlane", - "name": "Swimlane", - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "minimum_license_required": "gold", - "supported_feature_ids": [ - "alerting", - "cases", - "siem" - ] - }, - { - "id": ".index", - "name": "Index", - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "minimum_license_required": "basic", - "supported_feature_ids": [ - "alerting", - "uptime", - "siem" - ] - }, - { - "id": ".server-log", - "name": "Server log", - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "minimum_license_required": "basic", - "supported_feature_ids": [ - "alerting", - "uptime" - ] - } - ] } }, "responses": { @@ -7287,9 +7087,7 @@ "properties": { "error": { "type": "string", - "examples": [ - "Unauthorized" - ], + "example": "Unauthorized", "enum": [ "Unauthorized" ] @@ -7299,9 +7097,7 @@ }, "statusCode": { "type": "integer", - "examples": [ - 401 - ], + "example": 401, "enum": [ 401 ] @@ -7321,24 +7117,18 @@ "properties": { "error": { "type": "string", - "examples": [ - "Not Found" - ], + "example": "Not Found", "enum": [ "Not Found" ] }, "message": { "type": "string", - "examples": [ - "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" - ] + "example": "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" }, "statusCode": { "type": "integer", - "examples": [ - 404 - ], + "example": 404, "enum": [ 404 ] diff --git a/x-pack/plugins/actions/docs/openapi/bundled.yaml b/x-pack/plugins/actions/docs/openapi/bundled.yaml index c9628f9916c6f..95a0449bec192 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Connectors description: OpenAPI schema for Connectors endpoints @@ -17,14 +17,17 @@ tags: - name: connectors description: Connector APIs enable you to create and manage connectors. paths: - /api/actions/connector: + /s/{spaceId}/api/actions/connector: post: - summary: Creates a connector. - operationId: createConnector + summary: Create a connector + operationId: createConnectorWithSpaceId + description: | + You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' requestBody: required: true content: @@ -58,14 +61,17 @@ paths: $ref: '#/components/examples/create_xmatters_connector_response' '401': $ref: '#/components/responses/401' - /api/actions/connector/{connectorId}: + /s/{spaceId}/api/actions/connector/{connectorId}: get: - summary: Retrieves a connector by ID. - operationId: getConnector + summary: Get connector information + operationId: getConnectorWithSpaceId + description: | + You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: - connectors parameters: - $ref: '#/components/parameters/connector_id' + - $ref: '#/components/parameters/space_id' responses: '200': description: Indicates a successful call. @@ -81,13 +87,16 @@ paths: '404': $ref: '#/components/responses/404' delete: - summary: Deletes a connector. - operationId: deleteConnector + summary: Delete a connector + operationId: deleteConnectorWithSpaceId + description: | + You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered. tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/connector_id' + - $ref: '#/components/parameters/space_id' responses: '204': description: Indicates a successful call. @@ -96,21 +105,22 @@ paths: '404': $ref: '#/components/responses/404' post: - summary: Creates a connector. - operationId: createConnectorId + summary: Create a connector + operationId: createConnectorIdWithSpaceId + description: | + You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' - in: path name: connectorId - description: | - A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. + description: A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. required: true schema: type: string - examples: - - ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 requestBody: required: true content: @@ -133,13 +143,16 @@ paths: '401': $ref: '#/components/responses/401' put: - summary: Updates the attributes for a connector. - operationId: updateConnector + summary: Update a connector + operationId: updateConnectorWithSpaceId + description: | + You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/connector_id' + - $ref: '#/components/parameters/space_id' requestBody: required: true content: @@ -162,10 +175,97 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - /api/actions/connector/{connectorId}/_execute: + /s/{spaceId}/api/actions/connectors: + get: + summary: Get all connectors + operationId: getConnectorsWithSpaceId + description: | + You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + tags: + - connectors + parameters: + - $ref: '#/components/parameters/space_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/connector_response_properties' + examples: + getConnectorsResponse: + $ref: '#/components/examples/get_connectors_response' + '401': + $ref: '#/components/responses/401' + /s/{spaceId}/api/actions/connector_types: + get: + summary: Get all connector types + operationId: getConnectorTypesWithSpaceId + description: | + You do not need any Kibana feature privileges to run this API. + tags: + - connectors + parameters: + - $ref: '#/components/parameters/space_id' + - in: query + name: feature_id + description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). + schema: + $ref: '#/components/schemas/features' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + title: Get connector types response body properties + description: The properties vary for each connector type. + type: array + items: + type: object + properties: + enabled: + type: boolean + description: Indicates whether the connector type is enabled in Kibana. + example: true + enabled_in_config: + type: boolean + description: Indicates whether the connector type is enabled in the Kibana `.yml` file. + example: true + enabled_in_license: + type: boolean + description: Indicates whether the connector is enabled in the license. + example: true + id: + $ref: '#/components/schemas/connector_types' + minimum_license_required: + type: string + description: The license that is required to use the connector type. + example: basic + name: + type: string + description: The name of the connector type. + example: Index + supported_feature_ids: + type: array + description: The Kibana features that are supported by the connector type. + items: + $ref: '#/components/schemas/features' + example: + - alerting + - uptime + - siem + examples: + getConnectorTypesResponse: + $ref: '#/components/examples/get_connector_types_response' + '401': + $ref: '#/components/responses/401' + /s/{spaceId}/api/actions/connector/{connectorId}/_execute: post: - summary: Runs a connector. - operationId: runConnector + summary: Run a connector + operationId: runConnectorWithSpaceId description: | You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges. tags: @@ -173,6 +273,7 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/connector_id' + - $ref: '#/components/parameters/space_id' requestBody: required: true content: @@ -180,16 +281,10 @@ paths: schema: $ref: '#/components/schemas/run_connector_request' examples: - runCasesWebhookConnectorRequest: - $ref: '#/components/examples/run_cases_webhook_connector_request' - runEmailConnectorRequest: - $ref: '#/components/examples/run_email_connector_request' runIndexConnectorRequest: $ref: '#/components/examples/run_index_connector_request' runJiraConnectorRequest: $ref: '#/components/examples/run_jira_connector_request' - runPagerDutyConnectorRequest: - $ref: '#/components/examples/run_pagerduty_connector_request' runServerLogConnectorRequest: $ref: '#/components/examples/run_server_log_connector_request' runServiceNowITOMConnectorRequest: @@ -221,6 +316,10 @@ paths: description: An array of information returned from the action. items: type: object + message: + type: string + service_message: + type: string status: type: string description: The status of the action. @@ -228,16 +327,10 @@ paths: - error - ok examples: - runCasesWebhookConnectorResponse: - $ref: '#/components/examples/run_cases_webhook_connector_response' - runEmailConnectorResponse: - $ref: '#/components/examples/run_email_connector_response' runIndexConnectorResponse: $ref: '#/components/examples/run_index_connector_response' runJiraConnectorResponse: $ref: '#/components/examples/run_jira_connector_response' - runPagerDutyConnectorResponse: - $ref: '#/components/examples/run_pagerduty_connector_response' runServerLogConnectorResponse: $ref: '#/components/examples/run_server_log_connector_response' runServiceNowITOMConnectorResponse: @@ -248,106 +341,14 @@ paths: $ref: '#/components/examples/run_swimlane_connector_response' '401': $ref: '#/components/responses/401' - /api/actions/connectors: - get: - summary: Retrieves all connectors. - operationId: getConnectors - tags: - - connectors - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/connector_response_properties' - examples: - getConnectorsResponse: - $ref: '#/components/examples/get_connectors_response' - '401': - $ref: '#/components/responses/401' - /api/actions/connector_types: - get: - summary: Retrieves a list of all connector types. - operationId: getConnectorTypes - tags: - - connectors - parameters: - - in: query - name: feature_id - description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). - schema: - $ref: '#/components/schemas/features' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - title: Get connector types response body properties - description: The properties vary for each connector type. - type: array - items: - type: object - properties: - enabled: - type: boolean - description: Indicates whether the connector type is enabled in Kibana. - examples: - - true - enabled_in_config: - type: boolean - description: Indicates whether the connector type is enabled in the Kibana configuration file. - examples: - - true - enabled_in_license: - type: boolean - description: Indicates whether the connector is enabled in the license. - examples: - - true - id: - $ref: '#/components/schemas/connector_types' - is_system_action_type: - type: boolean - examples: - - false - minimum_license_required: - type: string - description: The license that is required to use the connector type. - examples: - - basic - name: - type: string - description: The name of the connector type. - examples: - - Index - supported_feature_ids: - type: array - description: The features that are supported by the connector type. - items: - $ref: '#/components/schemas/features' - examples: - - - alerting - - cases - - siem - examples: - getConnectorTypesServerlessResponse: - $ref: '#/components/examples/get_connector_types_generativeai_response' - '401': - $ref: '#/components/responses/401' - /s/{spaceId}/api/actions/connector: + /api/actions/connector: post: - summary: Creates a connector. - operationId: createConnectorWithSpaceId - description: | - You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + summary: Create a connector + operationId: createConnector tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - - $ref: '#/components/parameters/space_id' requestBody: required: true content: @@ -381,17 +382,14 @@ paths: $ref: '#/components/examples/create_xmatters_connector_response' '401': $ref: '#/components/responses/401' - /s/{spaceId}/api/actions/connector/{connectorId}: + /api/actions/connector/{connectorId}: get: - summary: Retrieves a connector by ID. - operationId: getConnectorWithSpaceId - description: | - You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + summary: Get a connector information + operationId: getConnector tags: - connectors parameters: - $ref: '#/components/parameters/connector_id' - - $ref: '#/components/parameters/space_id' responses: '200': description: Indicates a successful call. @@ -407,16 +405,13 @@ paths: '404': $ref: '#/components/responses/404' delete: - summary: Deletes a connector. - operationId: deleteConnectorWithSpaceId - description: | - You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered. + summary: Delete a connector + operationId: deleteConnector tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/connector_id' - - $ref: '#/components/parameters/space_id' responses: '204': description: Indicates a successful call. @@ -425,23 +420,20 @@ paths: '404': $ref: '#/components/responses/404' post: - summary: Creates a connector. - operationId: createConnectorIdWithSpaceId - description: | - You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + summary: Create a connector + operationId: createConnectorId tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - - $ref: '#/components/parameters/space_id' - in: path name: connectorId - description: A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. + description: | + A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. required: true schema: type: string - examples: - - ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 requestBody: required: true content: @@ -464,16 +456,13 @@ paths: '401': $ref: '#/components/responses/401' put: - summary: Updates the attributes for a connector. - operationId: updateConnectorWithSpaceId - description: | - You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + summary: Update a connector + operationId: updateConnector tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/connector_id' - - $ref: '#/components/parameters/space_id' requestBody: required: true content: @@ -496,110 +485,17 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - /s/{spaceId}/api/actions/connectors: - get: - summary: Retrieves all connectors. - operationId: getConnectorsWithSpaceId + /api/actions/connector/{connectorId}/_execute: + post: + summary: Run a connector + operationId: runConnector description: | - You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. - tags: - - connectors - parameters: - - $ref: '#/components/parameters/space_id' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/connector_response_properties' - examples: - getConnectorsResponse: - $ref: '#/components/examples/get_connectors_response' - '401': - $ref: '#/components/responses/401' - /s/{spaceId}/api/actions/connector_types: - get: - summary: Retrieves a list of all connector types. - operationId: getConnectorTypesWithSpaceId - description: | - You do not need any Kibana feature privileges to run this API. - tags: - - connectors - parameters: - - $ref: '#/components/parameters/space_id' - - in: query - name: feature_id - description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). - schema: - $ref: '#/components/schemas/features' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - title: Get connector types response body properties - description: The properties vary for each connector type. - type: array - items: - type: object - properties: - enabled: - type: boolean - description: Indicates whether the connector type is enabled in Kibana. - examples: - - true - enabled_in_config: - type: boolean - description: Indicates whether the connector type is enabled in the Kibana `.yml` file. - examples: - - true - enabled_in_license: - type: boolean - description: Indicates whether the connector is enabled in the license. - examples: - - true - id: - $ref: '#/components/schemas/connector_types' - minimum_license_required: - type: string - description: The license that is required to use the connector type. - examples: - - basic - name: - type: string - description: The name of the connector type. - examples: - - Index - supported_feature_ids: - type: array - description: The Kibana features that are supported by the connector type. - items: - $ref: '#/components/schemas/features' - examples: - - - alerting - - uptime - - siem - examples: - getConnectorTypesResponse: - $ref: '#/components/examples/get_connector_types_response' - '401': - $ref: '#/components/responses/401' - /s/{spaceId}/api/actions/connector/{connectorId}/_execute: - post: - summary: Runs a connector. - operationId: runConnectorWithSpaceId - description: | - You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges. + You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges. tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/connector_id' - - $ref: '#/components/parameters/space_id' requestBody: required: true content: @@ -607,10 +503,16 @@ paths: schema: $ref: '#/components/schemas/run_connector_request' examples: + runCasesWebhookConnectorRequest: + $ref: '#/components/examples/run_cases_webhook_connector_request' + runEmailConnectorRequest: + $ref: '#/components/examples/run_email_connector_request' runIndexConnectorRequest: $ref: '#/components/examples/run_index_connector_request' runJiraConnectorRequest: $ref: '#/components/examples/run_jira_connector_request' + runPagerDutyConnectorRequest: + $ref: '#/components/examples/run_pagerduty_connector_request' runServerLogConnectorRequest: $ref: '#/components/examples/run_server_log_connector_request' runServiceNowITOMConnectorRequest: @@ -642,10 +544,6 @@ paths: description: An array of information returned from the action. items: type: object - message: - type: string - service_message: - type: string status: type: string description: The status of the action. @@ -653,10 +551,16 @@ paths: - error - ok examples: + runCasesWebhookConnectorResponse: + $ref: '#/components/examples/run_cases_webhook_connector_response' + runEmailConnectorResponse: + $ref: '#/components/examples/run_email_connector_response' runIndexConnectorResponse: $ref: '#/components/examples/run_index_connector_response' runJiraConnectorResponse: $ref: '#/components/examples/run_jira_connector_response' + runPagerDutyConnectorResponse: + $ref: '#/components/examples/run_pagerduty_connector_response' runServerLogConnectorResponse: $ref: '#/components/examples/run_server_log_connector_response' runServiceNowITOMConnectorResponse: @@ -667,9 +571,92 @@ paths: $ref: '#/components/examples/run_swimlane_connector_response' '401': $ref: '#/components/responses/401' + /api/actions/connectors: + get: + summary: Get all connectors + operationId: getConnectors + tags: + - connectors + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/connector_response_properties' + examples: + getConnectorsResponse: + $ref: '#/components/examples/get_connectors_response' + '401': + $ref: '#/components/responses/401' + /api/actions/connector_types: + get: + summary: Get all connector types + operationId: getConnectorTypes + tags: + - connectors + parameters: + - in: query + name: feature_id + description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). + schema: + $ref: '#/components/schemas/features' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + title: Get connector types response body properties + description: The properties vary for each connector type. + type: array + items: + type: object + properties: + enabled: + type: boolean + description: Indicates whether the connector type is enabled in Kibana. + example: true + enabled_in_config: + type: boolean + description: Indicates whether the connector type is enabled in the Kibana configuration file. + example: true + enabled_in_license: + type: boolean + description: Indicates whether the connector is enabled in the license. + example: true + id: + $ref: '#/components/schemas/connector_types' + is_system_action_type: + type: boolean + example: false + minimum_license_required: + type: string + description: The license that is required to use the connector type. + example: basic + name: + type: string + description: The name of the connector type. + example: Index + supported_feature_ids: + type: array + description: The features that are supported by the connector type. + items: + $ref: '#/components/schemas/features' + example: + - alerting + - cases + - siem + examples: + getConnectorTypesServerlessResponse: + $ref: '#/components/examples/get_connector_types_generativeai_response' + '401': + $ref: '#/components/responses/401' /s/{spaceId}/api/actions/action/{actionId}: delete: - summary: Deletes a connector. + summary: Delete a connector operationId: legacyDeleteConnector deprecated: true description: | @@ -686,7 +673,7 @@ paths: '401': $ref: '#/components/responses/401' get: - summary: Retrieves a connector by ID. + summary: Get connector information operationId: legacyGetConnector description: Deprecated in 7.13.0. Use the get connector API instead. deprecated: true @@ -701,7 +688,7 @@ paths: '401': $ref: '#/components/responses/401' put: - summary: Updates the attributes for a connector. + summary: Update a connector operationId: legacyUpdateConnector deprecated: true description: Deprecated in 7.13.0. Use the update connector API instead. @@ -736,7 +723,7 @@ paths: $ref: '#/components/responses/404' /s/{spaceId}/api/actions: get: - summary: Retrieves all connectors. + summary: Get all connectors operationId: legacyGetConnectors deprecated: true description: Deprecated in 7.13.0. Use the get all connectors API instead. @@ -756,7 +743,7 @@ paths: '401': $ref: '#/components/responses/401' post: - summary: Creates a connector. + summary: Create a connector operationId: legacyCreateConnector deprecated: true description: Deprecated in 7.13.0. Use the create connector API instead. @@ -793,7 +780,7 @@ paths: $ref: '#/components/responses/401' /s/{spaceId}/api/actions/list_action_types: get: - summary: Retrieves a list of all connector types. + summary: Get connector types operationId: legacyGetConnectorTypes deprecated: true description: Deprecated in 7.13.0. Use the get all connector types API instead. @@ -822,8 +809,7 @@ paths: enabledInLicense: type: boolean description: Indicates whether the connector is enabled in the license. - examples: - - true + example: true id: type: string description: The unique identifier for the connector type. @@ -837,7 +823,7 @@ paths: $ref: '#/components/responses/401' /s/{spaceId}/api/actions/action/{actionId}/_execute: post: - summary: Runs a connector. + summary: Run a connector operationId: legacyRunConnector deprecated: true description: Deprecated in 7.13.0. Use the run connector API instead. @@ -903,24 +889,22 @@ components: name: kbn-xsrf description: Cross-site request forgery protection required: true - connector_id: + space_id: in: path - name: connectorId - description: An identifier for the connector. + 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 - examples: - - df770e30-8b8b-11ed-a780-3b746c987a81 - space_id: + example: default + connector_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. + name: connectorId + description: An identifier for the connector. required: true schema: type: string - examples: - - default + example: df770e30-8b8b-11ed-a780-3b746c987a81 action_id: in: path name: actionId @@ -928,8 +912,7 @@ components: required: true schema: type: string - examples: - - c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad + example: c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad schemas: create_connector_request_bedrock: title: Create Amazon Bedrock connector request @@ -948,13 +931,11 @@ components: description: The type of connector. enum: - .bedrock - examples: - - .bedrock + example: .bedrock name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_bedrock' create_connector_request_gemini: @@ -974,13 +955,11 @@ components: description: The type of connector. enum: - .gemini - examples: - - .gemini + example: .gemini name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_gemini' create_connector_request_cases_webhook: @@ -1000,13 +979,11 @@ components: description: The type of connector. enum: - .cases-webhook - examples: - - .cases-webhook + example: .cases-webhook name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_cases_webhook' create_connector_request_d3security: @@ -1027,13 +1004,11 @@ components: description: The type of connector. enum: - .d3security - examples: - - .d3security + example: .d3security name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_d3security' create_connector_request_email: @@ -1054,13 +1029,11 @@ components: description: The type of connector. enum: - .email - examples: - - .email + example: .email name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_email' create_connector_request_genai: @@ -1081,13 +1054,11 @@ components: description: The type of connector. enum: - .gen-ai - examples: - - .gen-ai + example: .gen-ai name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_genai' create_connector_request_index: @@ -1106,13 +1077,11 @@ components: description: The type of connector. enum: - .index - examples: - - .index + example: .index name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector create_connector_request_jira: title: Create Jira connector request description: The Jira connector uses the REST API v2 to create Jira issues. @@ -1130,13 +1099,11 @@ components: description: The type of connector. enum: - .jira - examples: - - .jira + example: .jira name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_jira' create_connector_request_opsgenie: @@ -1156,13 +1123,11 @@ components: description: The type of connector. enum: - .opsgenie - examples: - - .opsgenie + example: .opsgenie name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_opsgenie' create_connector_request_pagerduty: @@ -1183,13 +1148,11 @@ components: description: The type of connector. enum: - .pagerduty - examples: - - .pagerduty + example: .pagerduty name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_pagerduty' create_connector_request_resilient: @@ -1207,15 +1170,13 @@ components: connector_type_id: description: The type of connector. type: string - examples: - - .resilient + example: .resilient enum: - .resilient name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_resilient' create_connector_request_sentinelone: @@ -1237,13 +1198,11 @@ components: description: The type of connector. enum: - .sentinelone - examples: - - .sentinelone + example: .sentinelone name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_sentinelone' create_connector_request_serverlog: @@ -1259,13 +1218,11 @@ components: description: The type of connector. enum: - .server-log - examples: - - .server-log + example: .server-log name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector create_connector_request_servicenow: title: Create ServiceNow ITSM connector request description: | @@ -1284,13 +1241,11 @@ components: description: The type of connector. enum: - .servicenow - examples: - - .servicenow + example: .servicenow name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_servicenow' create_connector_request_servicenow_itom: @@ -1311,13 +1266,11 @@ components: description: The type of connector. enum: - .servicenow-itom - examples: - - .servicenow-itom + example: .servicenow-itom name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_servicenow' create_connector_request_servicenow_sir: @@ -1338,13 +1291,11 @@ components: description: The type of connector. enum: - .servicenow-sir - examples: - - .servicenow-sir + example: .servicenow-sir name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_servicenow' create_connector_request_slack_api: @@ -1363,13 +1314,11 @@ components: description: The type of connector. enum: - .slack_api - examples: - - .slack_api + example: .slack_api name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_slack_api' create_connector_request_slack_webhook: @@ -1386,13 +1335,11 @@ components: description: The type of connector. enum: - .slack - examples: - - .slack + example: .slack name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_slack_webhook' create_connector_request_swimlane: @@ -1412,13 +1359,11 @@ components: description: The type of connector. enum: - .swimlane - examples: - - .swimlane + example: .swimlane name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_swimlane' create_connector_request_teams: @@ -1435,13 +1380,11 @@ components: description: The type of connector. enum: - .teams - examples: - - .teams + example: .teams name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_teams' create_connector_request_tines: @@ -1462,13 +1405,11 @@ components: description: The type of connector. enum: - .tines - examples: - - .tines + example: .tines name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_tines' create_connector_request_torq: @@ -1489,13 +1430,11 @@ components: description: The type of connector. enum: - .torq - examples: - - .torq + example: .torq name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_torq' create_connector_request_webhook: @@ -1516,13 +1455,11 @@ components: description: The type of connector. enum: - .webhook - examples: - - .webhook + example: .webhook name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_webhook' create_connector_request_xmatters: @@ -1543,13 +1480,11 @@ components: description: The type of connector. enum: - .xmatters - examples: - - .xmatters + example: .xmatters name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_xmatters' config_properties_bedrock: @@ -1631,8 +1566,7 @@ components: type: string description: | A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is `case.comment`. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. - examples: - - '{"body": {{{case.comment}}}}' + example: '{"body": {{{case.comment}}}}' createCommentMethod: type: string description: | @@ -1646,14 +1580,12 @@ components: type: string description: | The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts. - examples: - - https://example.com/issue/{{{external.system.id}}}/comment + example: https://example.com/issue/{{{external.system.id}}}/comment createIncidentJson: type: string description: | A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. - examples: - - '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' + example: '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' createIncidentMethod: type: string description: | @@ -1677,8 +1609,7 @@ components: type: string description: | The REST API URL to get the case by ID from the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. - examples: - - https://example.com/issue/{{{external.system.id}}} + example: https://example.com/issue/{{{external.system.id}}} hasAuth: type: boolean description: If true, a username and password for login type authentication must be provided. @@ -1691,8 +1622,7 @@ components: type: string description: | The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. - examples: - - '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' + example: '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' updateIncidentMethod: type: string description: | @@ -1706,14 +1636,12 @@ components: type: string description: | The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. - examples: - - https://example.com/issue/{{{external.system.ID}}} + example: https://example.com/issue/{{{external.system.ID}}} viewIncidentUrl: type: string description: | The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL. - examples: - - https://testing-jira.atlassian.net/browse/{{{external.system.title}}} + example: https://testing-jira.atlassian.net/browse/{{{external.system.title}}} secrets_properties_cases_webhook: title: Connector secrets properties for Webhook - Case Management connector type: object @@ -1755,9 +1683,8 @@ components: clientId: description: | The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. - type: - - string - - 'null' + type: string + nullable: true from: description: | The from address for all emails sent by the connector. It must be specified in `user@host-name` format. @@ -1772,9 +1699,8 @@ components: The host name of the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. type: string oauthTokenUrl: - type: - - string - - 'null' + type: string + nullable: true port: description: | The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. @@ -1797,9 +1723,8 @@ components: tenantId: description: | The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. - type: - - string - - 'null' + type: string + nullable: true secrets_properties_email: title: Connector secrets properties for an email connector description: Defines secrets for connectors when type is `.email`. @@ -1883,9 +1808,8 @@ components: executionTimeField: description: A field that indicates when the document was indexed. default: null - type: - - string - - 'null' + type: string + nullable: true index: description: The Elasticsearch index to be written to. type: string @@ -1950,11 +1874,9 @@ components: properties: apiUrl: description: The PagerDuty event URL. - type: - - string - - 'null' - examples: - - https://events.pagerduty.com/v2/enqueue + type: string + nullable: true + example: https://events.pagerduty.com/v2/enqueue secrets_properties_pagerduty: title: Connector secrets properties for a PagerDuty connector description: Defines secrets for connectors when type is `.pagerduty`. @@ -2390,10 +2312,10 @@ components: properties: authType: type: string + nullable: true enum: - webhook-authentication-basic - webhook-authentication-ssl - - 'null' description: | The type of authentication to use: basic, SSL, or none. ca: @@ -2412,9 +2334,8 @@ components: description: | If `true`, a user name and password must be provided for login type authentication. headers: - type: - - object - - 'null' + type: object + nullable: true description: A set of key-value pairs sent as headers with the request. method: type: string @@ -2467,9 +2388,8 @@ components: configUrl: description: | The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`. - type: - - string - - 'null' + type: string + nullable: true usesBasic: description: Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`). type: boolean @@ -2952,9 +2872,8 @@ components: - name properties: config: - type: - - object - - 'null' + type: object + nullable: true connector_type_id: type: string description: The type of connector. @@ -3340,30 +3259,25 @@ components: is_deprecated: type: boolean description: Indicates whether the connector type is deprecated. - examples: - - false + example: false is_missing_secrets: type: boolean description: Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type. - examples: - - false + example: false is_preconfigured: type: boolean description: | Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. - examples: - - false + example: false is_system_action: type: boolean description: Indicates whether the connector is used for system actions. - examples: - - false + example: false referenced_by_count: type: integer description: | Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API. - examples: - - 2 + example: 2 connector_response_properties: title: Connector response properties description: The properties vary depending on the connector type. @@ -3459,8 +3373,7 @@ components: name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_cases_webhook' update_connector_request_d3security: @@ -3657,8 +3570,7 @@ components: name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_swimlane' update_connector_request_teams: @@ -3760,6 +3672,48 @@ components: - $ref: '#/components/schemas/update_connector_request_torq' - $ref: '#/components/schemas/update_connector_request_webhook' - $ref: '#/components/schemas/update_connector_request_xmatters' + features: + type: string + description: | + The feature that uses the connector. + enum: + - alerting + - cases + - generativeAIForSecurity + - generativeAIForObservability + - generativeAIForSearchPlayground + - siem + - uptime + connector_types: + title: Connector types + type: string + description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. + enum: + - .bedrock + - .gemini + - .cases-webhook + - .d3security + - .email + - .gen-ai + - .index + - .jira + - .opsgenie + - .pagerduty + - .resilient + - .sentinelone + - .servicenow + - .servicenow-itom + - .servicenow-sir + - .server-log + - .slack + - .slack_api + - .swimlane + - .teams + - .tines + - .torq + - .webhook + - .xmatters + example: .server-log run_connector_params_acknowledge_resolve_pagerduty: title: PagerDuty connector parameters description: Test an action that acknowledges or resolves a PagerDuty alert. @@ -3876,13 +3830,11 @@ components: class: description: The class or type of the event. type: string - examples: - - cpu load + example: cpu load component: description: The component of the source machine that is responsible for the event. type: string - examples: - - eth0 + example: eth0 customDetails: description: Additional details to add to the event. type: object @@ -3899,8 +3851,7 @@ components: group: description: The logical grouping of components of a service. type: string - examples: - - app-stack + example: app-stack links: description: A list of links to add to the event. type: array @@ -4040,17 +3991,15 @@ components: - externalId properties: correlation_id: - type: - - 'null' - - string + type: string + nullable: true description: | An identifier that is assigned to the incident when it is created by the connector. NOTE: If you use the default value and the rule generates multiple alerts that use the same alert IDs, the latest open incident for this correlation ID is closed unless you specify the external ID. maxLength: 100 default: '{{rule.id}}:{{alert.id}}' externalId: - type: - - 'null' - - string + type: string + nullable: true description: The unique identifier (`incidentId`) for the incident in ServiceNow. run_connector_subaction_createalert: title: The createAlert subaction @@ -4085,9 +4034,9 @@ components: type: object description: The custom properties of the alert. additionalProperties: true - examples: - - key1: value1 - key2: value2 + example: + key1: value1 + key2: value2 entity: type: string description: The domain of the alert. For example, the application or server name. @@ -4185,8 +4134,7 @@ components: id: type: string description: The Jira issue type identifier. - examples: - - 10024 + example: 10024 run_connector_subaction_getchoices: title: The getChoices subaction type: object @@ -4244,8 +4192,7 @@ components: externalId: type: string description: The Jira, ServiceNow ITSM, or ServiceNow SecOps issue identifier. - examples: - - 71778 + example: 71778 run_connector_subaction_issue: title: The issue subaction type: object @@ -4266,8 +4213,7 @@ components: id: type: string description: The Jira issue identifier. - examples: - - 71778 + example: 71778 run_connector_subaction_issues: title: The issues subaction type: object @@ -4556,49 +4502,6 @@ components: issues: '#/components/schemas/run_connector_subaction_issues' issueTypes: '#/components/schemas/run_connector_subaction_issuetypes' pushToService: '#/components/schemas/run_connector_subaction_pushtoservice' - features: - type: string - description: | - The feature that uses the connector. - enum: - - alerting - - cases - - generativeAIForSecurity - - generativeAIForObservability - - generativeAIForSearchPlayground - - siem - - uptime - connector_types: - title: Connector types - type: string - description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. - enum: - - .bedrock - - .gemini - - .cases-webhook - - .d3security - - .email - - .gen-ai - - .index - - .jira - - .opsgenie - - .pagerduty - - .resilient - - .sentinelone - - .servicenow - - .servicenow-itom - - .servicenow-sir - - .server-log - - .slack - - .slack_api - - .swimlane - - .teams - - .tines - - .torq - - .webhook - - .xmatters - examples: - - .server-log action_response_properties: title: Action response properties description: The properties vary depending on the action type. @@ -4749,37 +4652,60 @@ components: name: updated-connector config: index: updated-index - run_cases_webhook_connector_request: - summary: Run a Webhook - Case Management connector to create a case. + get_connectors_response: + summary: A list of connectors value: - params: - subAction: pushToService - subActionParams: - comments: - - commentId: 1 - comment: A comment about the incident. - incident: - title: Case title - description: Description of the incident. - tags: - - tag1 - - tag2 - severity: low - status: open - id: caseID - run_email_connector_request: - summary: Send an email message from an email connector. + - id: preconfigured-email-connector + name: my-preconfigured-email-notification + connector_type_id: .email + is_preconfigured: true + is_deprecated: false + referenced_by_count: 0 + is_system_action: false + - id: e07d0c80-8b8b-11ed-a780-3b746c987a81 + name: my-index-connector + config: + index: test-index + refresh: false + executionTimeField: null + connector_type_id: .index + is_preconfigured: false + is_deprecated: false + referenced_by_count: 2 + is_missing_secrets: false + is_system_action: false + get_connector_types_response: + summary: A list of connector types value: - params: - bcc: - - user1@example.com - cc: - - user2@example.com - - user3@example.com - message: Test email message. - subject: Test message subject - to: - - user4@example.com + - id: .swimlane + name: Swimlane + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: gold + supported_feature_ids: + - alerting + - cases + - siem + - id: .index + name: Index + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: basic + supported_feature_ids: + - alerting + - uptime + - siem + - id: .server-log + name: Server log + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: basic + supported_feature_ids: + - alerting + - uptime run_index_connector_request: summary: Run an index connector. value: @@ -4793,17 +4719,6 @@ components: value: params: subAction: issueTypes - run_pagerduty_connector_request: - summary: Run a PagerDuty connector to trigger an alert. - value: - params: - eventAction: trigger - summary: A brief event summary - links: - - href: http://example.com/pagerduty - text: An example link - customDetails: - my_data_1: test data run_server_log_connector_request: summary: Run a server log connector. value: @@ -4841,43 +4756,6 @@ components: caseId: '1000' caseName: Case name description: Description of the incident. - run_cases_webhook_connector_response: - summary: Response from a pushToService action for a Webhook - Case Management connector. - value: - connector_id: 1824b5b8-c005-4dcc-adac-57f92db46459 - data: - id: 100665 - title: TEST-29034 - url: https://example.com/browse/TEST-29034 - pushedDate: '2023-12-05T19:43:36.360Z' - comments: - - commentId: 1 - pushedDate: '2023-12-05T19:43:36.360Z' - status: ok - run_email_connector_response: - summary: Response for sending a message from an email connector. - value: - connector_id: 7fc7b9a0-ecc9-11ec-8736-e7d63118c907 - data: - accepted: - - user1@example.com - - user2@example.com - - user3@example.com - - user4@example.com - envelope: - from: tester@example.com - to: - - user1@example.com - - user2@example.com - - user3@example.com - - user4@example.com - envelopeTime: 8 - messageTime: 3 - messageSize: 729 - response: 250 Message queued as QzEXKcGJ - messageId: <08a92d29-642a-0706-750c-de5996bd5cf3@example.com> - rejected: [] - status: ok run_index_connector_response: summary: Response from running an index connector. value: @@ -4917,15 +4795,6 @@ components: - id: 10000 name: Epic status: ok - run_pagerduty_connector_response: - summary: Response from running a PagerDuty connector. - value: - connector_id: 45de9f70-954f-4608-b12a-db7cf808e49d - data: - dedup_key: 5115e138b26b484a81eaea779faa6016 - message: Event processed - status: success - status: ok run_server_log_connector_response: summary: Response from running a server log connector. value: @@ -5020,28 +4889,94 @@ components: - commentId: 1 pushedDate: '2022-09-08T16:52:27.865Z' status: ok - get_connectors_response: - summary: A list of connectors + run_cases_webhook_connector_request: + summary: Run a Webhook - Case Management connector to create a case. value: - - id: preconfigured-email-connector - name: my-preconfigured-email-notification - connector_type_id: .email - is_preconfigured: true - is_deprecated: false - referenced_by_count: 0 - is_system_action: false - - id: e07d0c80-8b8b-11ed-a780-3b746c987a81 - name: my-index-connector - config: - index: test-index - refresh: false - executionTimeField: null - connector_type_id: .index - is_preconfigured: false - is_deprecated: false - referenced_by_count: 2 - is_missing_secrets: false - is_system_action: false + params: + subAction: pushToService + subActionParams: + comments: + - commentId: 1 + comment: A comment about the incident. + incident: + title: Case title + description: Description of the incident. + tags: + - tag1 + - tag2 + severity: low + status: open + id: caseID + run_email_connector_request: + summary: Send an email message from an email connector. + value: + params: + bcc: + - user1@example.com + cc: + - user2@example.com + - user3@example.com + message: Test email message. + subject: Test message subject + to: + - user4@example.com + run_pagerduty_connector_request: + summary: Run a PagerDuty connector to trigger an alert. + value: + params: + eventAction: trigger + summary: A brief event summary + links: + - href: http://example.com/pagerduty + text: An example link + customDetails: + my_data_1: test data + run_cases_webhook_connector_response: + summary: Response from a pushToService action for a Webhook - Case Management connector. + value: + connector_id: 1824b5b8-c005-4dcc-adac-57f92db46459 + data: + id: 100665 + title: TEST-29034 + url: https://example.com/browse/TEST-29034 + pushedDate: '2023-12-05T19:43:36.360Z' + comments: + - commentId: 1 + pushedDate: '2023-12-05T19:43:36.360Z' + status: ok + run_email_connector_response: + summary: Response for sending a message from an email connector. + value: + connector_id: 7fc7b9a0-ecc9-11ec-8736-e7d63118c907 + data: + accepted: + - user1@example.com + - user2@example.com + - user3@example.com + - user4@example.com + envelope: + from: tester@example.com + to: + - user1@example.com + - user2@example.com + - user3@example.com + - user4@example.com + envelopeTime: 8 + messageTime: 3 + messageSize: 729 + response: 250 Message queued as QzEXKcGJ + messageId: <08a92d29-642a-0706-750c-de5996bd5cf3@example.com> + rejected: [] + status: ok + run_pagerduty_connector_response: + summary: Response from running a PagerDuty connector. + value: + connector_id: 45de9f70-954f-4608-b12a-db7cf808e49d + data: + dedup_key: 5115e138b26b484a81eaea779faa6016 + message: Event processed + status: success + status: ok get_connector_types_generativeai_response: summary: A list of connector types for the `generativeAI` feature. value: @@ -5076,38 +5011,6 @@ components: supported_feature_ids: - generativeAIForSecurity is_system_action_type: false - get_connector_types_response: - summary: A list of connector types - value: - - id: .swimlane - name: Swimlane - enabled: true - enabled_in_config: true - enabled_in_license: true - minimum_license_required: gold - supported_feature_ids: - - alerting - - cases - - siem - - id: .index - name: Index - enabled: true - enabled_in_config: true - enabled_in_license: true - minimum_license_required: basic - supported_feature_ids: - - alerting - - uptime - - siem - - id: .server-log - name: Server log - enabled: true - enabled_in_config: true - enabled_in_license: true - minimum_license_required: basic - supported_feature_ids: - - alerting - - uptime responses: '401': description: Authorization information is missing or invalid. @@ -5119,16 +5022,14 @@ components: properties: error: type: string - examples: - - Unauthorized + example: Unauthorized enum: - Unauthorized message: type: string statusCode: type: integer - examples: - - 401 + example: 401 enum: - 401 '404': @@ -5141,18 +5042,15 @@ components: properties: error: type: string - examples: - - Not Found + example: Not Found enum: - Not Found message: type: string - examples: - - Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found + example: Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found statusCode: type: integer - examples: - - 404 + example: 404 enum: - 404 200_actions: diff --git a/x-pack/plugins/actions/docs/openapi/bundled_serverless.json b/x-pack/plugins/actions/docs/openapi/bundled_serverless.json index 8de6f01f7f43a..928dbbfd758d7 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled_serverless.json +++ b/x-pack/plugins/actions/docs/openapi/bundled_serverless.json @@ -1,5 +1,5 @@ { - "openapi": "3.1.0", + "openapi": "3.0.3", "info": { "title": "Connectors", "description": "OpenAPI schema for connectors in Serverless projects", @@ -36,7 +36,7 @@ "paths": { "/api/actions/connector": { "post": { - "summary": "Creates a connector.", + "summary": "Create a connector", "operationId": "createConnector", "tags": [ "connectors" @@ -103,7 +103,7 @@ }, "/api/actions/connector/{connectorId}": { "get": { - "summary": "Retrieves a connector by ID.", + "summary": "Get a connector information", "operationId": "getConnector", "tags": [ "connectors" @@ -138,7 +138,7 @@ } }, "delete": { - "summary": "Deletes a connector.", + "summary": "Delete a connector", "operationId": "deleteConnector", "tags": [ "connectors" @@ -164,7 +164,7 @@ } }, "post": { - "summary": "Creates a connector.", + "summary": "Create a connector", "operationId": "createConnectorId", "tags": [ "connectors" @@ -180,9 +180,7 @@ "required": true, "schema": { "type": "string", - "examples": [ - "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" - ] + "example": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" } } ], @@ -223,7 +221,7 @@ } }, "put": { - "summary": "Updates the attributes for a connector.", + "summary": "Update a connector", "operationId": "updateConnector", "tags": [ "connectors" @@ -276,7 +274,7 @@ }, "/api/actions/connectors": { "get": { - "summary": "Retrieves all connectors.", + "summary": "Get all connectors", "operationId": "getConnectors", "tags": [ "connectors" @@ -308,7 +306,7 @@ }, "/api/actions/connector_types": { "get": { - "summary": "Retrieves a list of all connector types.", + "summary": "Get all connector types", "operationId": "getConnectorTypes", "tags": [ "connectors" @@ -338,46 +336,34 @@ "enabled": { "type": "boolean", "description": "Indicates whether the connector type is enabled in Kibana.", - "examples": [ - true - ] + "example": true }, "enabled_in_config": { "type": "boolean", "description": "Indicates whether the connector type is enabled in the Kibana configuration file.", - "examples": [ - true - ] + "example": true }, "enabled_in_license": { "type": "boolean", "description": "Indicates whether the connector is enabled in the license.", - "examples": [ - true - ] + "example": true }, "id": { "$ref": "#/components/schemas/connector_types" }, "is_system_action_type": { "type": "boolean", - "examples": [ - false - ] + "example": false }, "minimum_license_required": { "type": "string", "description": "The license that is required to use the connector type.", - "examples": [ - "basic" - ] + "example": "basic" }, "name": { "type": "string", "description": "The name of the connector type.", - "examples": [ - "Index" - ] + "example": "Index" }, "supported_feature_ids": { "type": "array", @@ -385,12 +371,10 @@ "items": { "$ref": "#/components/schemas/features" }, - "examples": [ - [ - "alerting", - "cases", - "siem" - ] + "example": [ + "alerting", + "cases", + "siem" ] } } @@ -417,7 +401,7 @@ "type": "apiKey", "in": "header", "name": "Authorization", - "description": "e.g. Authorization: ApiKey base64AccessApiKey" + "description": "Serverless APIs support only key-based authentication. You must create an API key and use the encoded value in the request header. For example: 'Authorization: ApiKey base64AccessApiKey'.\n" } }, "parameters": { @@ -437,9 +421,7 @@ "required": true, "schema": { "type": "string", - "examples": [ - "df770e30-8b8b-11ed-a780-3b746c987a81" - ] + "example": "df770e30-8b8b-11ed-a780-3b746c987a81" } } }, @@ -464,16 +446,12 @@ "enum": [ ".bedrock" ], - "examples": [ - ".bedrock" - ] + "example": ".bedrock" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_bedrock" @@ -500,16 +478,12 @@ "enum": [ ".gemini" ], - "examples": [ - ".gemini" - ] + "example": ".gemini" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_gemini" @@ -535,16 +509,12 @@ "enum": [ ".cases-webhook" ], - "examples": [ - ".cases-webhook" - ] + "example": ".cases-webhook" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_cases_webhook" @@ -571,16 +541,12 @@ "enum": [ ".d3security" ], - "examples": [ - ".d3security" - ] + "example": ".d3security" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_d3security" @@ -607,16 +573,12 @@ "enum": [ ".email" ], - "examples": [ - ".email" - ] + "example": ".email" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_email" @@ -643,16 +605,12 @@ "enum": [ ".gen-ai" ], - "examples": [ - ".gen-ai" - ] + "example": ".gen-ai" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_genai" @@ -678,16 +636,12 @@ "enum": [ ".index" ], - "examples": [ - ".index" - ] + "example": ".index" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" } } }, @@ -711,16 +665,12 @@ "enum": [ ".jira" ], - "examples": [ - ".jira" - ] + "example": ".jira" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_jira" @@ -747,16 +697,12 @@ "enum": [ ".opsgenie" ], - "examples": [ - ".opsgenie" - ] + "example": ".opsgenie" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_opsgenie" @@ -783,16 +729,12 @@ "enum": [ ".pagerduty" ], - "examples": [ - ".pagerduty" - ] + "example": ".pagerduty" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_pagerduty" @@ -816,9 +758,7 @@ "connector_type_id": { "description": "The type of connector.", "type": "string", - "examples": [ - ".resilient" - ], + "example": ".resilient", "enum": [ ".resilient" ] @@ -826,9 +766,7 @@ "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_resilient" @@ -856,16 +794,12 @@ "enum": [ ".sentinelone" ], - "examples": [ - ".sentinelone" - ] + "example": ".sentinelone" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_sentinelone" @@ -887,16 +821,12 @@ "enum": [ ".server-log" ], - "examples": [ - ".server-log" - ] + "example": ".server-log" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" } } }, @@ -920,16 +850,12 @@ "enum": [ ".servicenow" ], - "examples": [ - ".servicenow" - ] + "example": ".servicenow" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_servicenow" @@ -956,16 +882,12 @@ "enum": [ ".servicenow-itom" ], - "examples": [ - ".servicenow-itom" - ] + "example": ".servicenow-itom" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_servicenow" @@ -992,16 +914,12 @@ "enum": [ ".servicenow-sir" ], - "examples": [ - ".servicenow-sir" - ] + "example": ".servicenow-sir" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_servicenow" @@ -1027,16 +945,12 @@ "enum": [ ".slack_api" ], - "examples": [ - ".slack_api" - ] + "example": ".slack_api" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_slack_api" @@ -1059,16 +973,12 @@ "enum": [ ".slack" ], - "examples": [ - ".slack" - ] + "example": ".slack" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_slack_webhook" @@ -1095,16 +1005,12 @@ "enum": [ ".swimlane" ], - "examples": [ - ".swimlane" - ] + "example": ".swimlane" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_swimlane" @@ -1127,16 +1033,12 @@ "enum": [ ".teams" ], - "examples": [ - ".teams" - ] + "example": ".teams" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_teams" @@ -1163,16 +1065,12 @@ "enum": [ ".tines" ], - "examples": [ - ".tines" - ] + "example": ".tines" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_tines" @@ -1199,16 +1097,12 @@ "enum": [ ".torq" ], - "examples": [ - ".torq" - ] + "example": ".torq" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_torq" @@ -1235,16 +1129,12 @@ "enum": [ ".webhook" ], - "examples": [ - ".webhook" - ] + "example": ".webhook" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_webhook" @@ -1271,16 +1161,12 @@ "enum": [ ".xmatters" ], - "examples": [ - ".xmatters" - ] + "example": ".xmatters" }, "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_xmatters" @@ -1386,9 +1272,7 @@ "createCommentJson": { "type": "string", "description": "A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is `case.comment`. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.\n", - "examples": [ - "{\"body\": {{{case.comment}}}}" - ] + "example": "{\"body\": {{{case.comment}}}}" }, "createCommentMethod": { "type": "string", @@ -1403,16 +1287,12 @@ "createCommentUrl": { "type": "string", "description": "The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts.\n", - "examples": [ - "https://example.com/issue/{{{external.system.id}}}/comment" - ] + "example": "https://example.com/issue/{{{external.system.id}}}/comment" }, "createIncidentJson": { "type": "string", "description": "A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.\n", - "examples": [ - "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" - ] + "example": "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" }, "createIncidentMethod": { "type": "string", @@ -1439,9 +1319,7 @@ "getIncidentUrl": { "type": "string", "description": "The REST API URL to get the case by ID from the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.\n", - "examples": [ - "https://example.com/issue/{{{external.system.id}}}" - ] + "example": "https://example.com/issue/{{{external.system.id}}}" }, "hasAuth": { "type": "boolean", @@ -1455,9 +1333,7 @@ "updateIncidentJson": { "type": "string", "description": "The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.\n", - "examples": [ - "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" - ] + "example": "{\"fields\": {\"summary\": {{{case.title}}},\"description\": {{{case.description}}},\"labels\": {{{case.tags}}}}}" }, "updateIncidentMethod": { "type": "string", @@ -1472,16 +1348,12 @@ "updateIncidentUrl": { "type": "string", "description": "The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n", - "examples": [ - "https://example.com/issue/{{{external.system.ID}}}" - ] + "example": "https://example.com/issue/{{{external.system.ID}}}" }, "viewIncidentUrl": { "type": "string", "description": "The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL.\n", - "examples": [ - "https://testing-jira.atlassian.net/browse/{{{external.system.title}}}" - ] + "example": "https://testing-jira.atlassian.net/browse/{{{external.system.title}}}" } } }, @@ -1537,10 +1409,8 @@ "properties": { "clientId": { "description": "The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required.\n", - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "from": { "description": "The from address for all emails sent by the connector. It must be specified in `user@host-name` format.\n", @@ -1556,10 +1426,8 @@ "type": "string" }, "oauthTokenUrl": { - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "port": { "description": "The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. \n", @@ -1583,10 +1451,8 @@ }, "tenantId": { "description": "The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required.\n", - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true } } }, @@ -1698,10 +1564,8 @@ "executionTimeField": { "description": "A field that indicates when the document was indexed.", "default": null, - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "index": { "description": "The Elasticsearch index to be written to.", @@ -1787,13 +1651,9 @@ "properties": { "apiUrl": { "description": "The PagerDuty event URL.", - "type": [ - "string", - "null" - ], - "examples": [ - "https://events.pagerduty.com/v2/enqueue" - ] + "type": "string", + "nullable": true, + "example": "https://events.pagerduty.com/v2/enqueue" } } }, @@ -2363,10 +2223,10 @@ "properties": { "authType": { "type": "string", + "nullable": true, "enum": [ "webhook-authentication-basic", - "webhook-authentication-ssl", - "null" + "webhook-authentication-ssl" ], "description": "The type of authentication to use: basic, SSL, or none.\n" }, @@ -2387,10 +2247,8 @@ "description": "If `true`, a user name and password must be provided for login type authentication.\n" }, "headers": { - "type": [ - "object", - "null" - ], + "type": "object", + "nullable": true, "description": "A set of key-value pairs sent as headers with the request." }, "method": { @@ -2452,10 +2310,8 @@ "properties": { "configUrl": { "description": "The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`.\n", - "type": [ - "string", - "null" - ] + "type": "string", + "nullable": true }, "usesBasic": { "description": "Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`).", @@ -3152,10 +3008,8 @@ ], "properties": { "config": { - "type": [ - "object", - "null" - ] + "type": "object", + "nullable": true }, "connector_type_id": { "type": "string", @@ -3695,37 +3549,27 @@ "is_deprecated": { "type": "boolean", "description": "Indicates whether the connector type is deprecated.", - "examples": [ - false - ] + "example": false }, "is_missing_secrets": { "type": "boolean", "description": "Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.", - "examples": [ - false - ] + "example": false }, "is_preconfigured": { "type": "boolean", "description": "Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. \n", - "examples": [ - false - ] + "example": false }, "is_system_action": { "type": "boolean", "description": "Indicates whether the connector is used for system actions.", - "examples": [ - false - ] + "example": false }, "referenced_by_count": { "type": "integer", "description": "Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API.\n", - "examples": [ - 2 - ] + "example": 2 }, "connector_response_properties": { "title": "Connector response properties", @@ -3888,9 +3732,7 @@ "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_cases_webhook" @@ -4167,9 +4009,7 @@ "name": { "type": "string", "description": "The display name for the connector.", - "examples": [ - "my-connector" - ] + "example": "my-connector" }, "secrets": { "$ref": "#/components/schemas/secrets_properties_swimlane" @@ -4395,9 +4235,7 @@ ".webhook", ".xmatters" ], - "examples": [ - ".server-log" - ] + "example": ".server-log" } }, "examples": { @@ -4646,9 +4484,7 @@ "properties": { "error": { "type": "string", - "examples": [ - "Unauthorized" - ], + "example": "Unauthorized", "enum": [ "Unauthorized" ] @@ -4658,9 +4494,7 @@ }, "statusCode": { "type": "integer", - "examples": [ - 401 - ], + "example": 401, "enum": [ 401 ] @@ -4680,24 +4514,18 @@ "properties": { "error": { "type": "string", - "examples": [ - "Not Found" - ], + "example": "Not Found", "enum": [ "Not Found" ] }, "message": { "type": "string", - "examples": [ - "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" - ] + "example": "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" }, "statusCode": { "type": "integer", - "examples": [ - 404 - ], + "example": 404, "enum": [ 404 ] diff --git a/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml b/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml index ab5cf28a73848..4fdc184e3fb90 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Connectors description: OpenAPI schema for connectors in Serverless projects @@ -21,7 +21,7 @@ tags: paths: /api/actions/connector: post: - summary: Creates a connector. + summary: Create a connector operationId: createConnector tags: - connectors @@ -62,7 +62,7 @@ paths: $ref: '#/components/responses/401' /api/actions/connector/{connectorId}: get: - summary: Retrieves a connector by ID. + summary: Get a connector information operationId: getConnector tags: - connectors @@ -83,7 +83,7 @@ paths: '404': $ref: '#/components/responses/404' delete: - summary: Deletes a connector. + summary: Delete a connector operationId: deleteConnector tags: - connectors @@ -98,7 +98,7 @@ paths: '404': $ref: '#/components/responses/404' post: - summary: Creates a connector. + summary: Create a connector operationId: createConnectorId tags: - connectors @@ -111,8 +111,7 @@ paths: required: true schema: type: string - examples: - - ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 requestBody: required: true content: @@ -135,7 +134,7 @@ paths: '401': $ref: '#/components/responses/401' put: - summary: Updates the attributes for a connector. + summary: Update a connector operationId: updateConnector tags: - connectors @@ -166,7 +165,7 @@ paths: $ref: '#/components/responses/404' /api/actions/connectors: get: - summary: Retrieves all connectors. + summary: Get all connectors operationId: getConnectors tags: - connectors @@ -186,7 +185,7 @@ paths: $ref: '#/components/responses/401' /api/actions/connector_types: get: - summary: Retrieves a list of all connector types. + summary: Get all connector types operationId: getConnectorTypes tags: - connectors @@ -211,43 +210,37 @@ paths: enabled: type: boolean description: Indicates whether the connector type is enabled in Kibana. - examples: - - true + example: true enabled_in_config: type: boolean description: Indicates whether the connector type is enabled in the Kibana configuration file. - examples: - - true + example: true enabled_in_license: type: boolean description: Indicates whether the connector is enabled in the license. - examples: - - true + example: true id: $ref: '#/components/schemas/connector_types' is_system_action_type: type: boolean - examples: - - false + example: false minimum_license_required: type: string description: The license that is required to use the connector type. - examples: - - basic + example: basic name: type: string description: The name of the connector type. - examples: - - Index + example: Index supported_feature_ids: type: array description: The features that are supported by the connector type. items: $ref: '#/components/schemas/features' - examples: - - - alerting - - cases - - siem + example: + - alerting + - cases + - siem examples: getConnectorTypesServerlessResponse: $ref: '#/components/examples/get_connector_types_generativeai_response' @@ -259,7 +252,8 @@ components: type: apiKey in: header name: Authorization - description: 'e.g. Authorization: ApiKey base64AccessApiKey' + description: | + Serverless APIs support only key-based authentication. You must create an API key and use the encoded value in the request header. For example: 'Authorization: ApiKey base64AccessApiKey'. parameters: kbn_xsrf: schema: @@ -275,8 +269,7 @@ components: required: true schema: type: string - examples: - - df770e30-8b8b-11ed-a780-3b746c987a81 + example: df770e30-8b8b-11ed-a780-3b746c987a81 schemas: create_connector_request_bedrock: title: Create Amazon Bedrock connector request @@ -295,13 +288,11 @@ components: description: The type of connector. enum: - .bedrock - examples: - - .bedrock + example: .bedrock name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_bedrock' create_connector_request_gemini: @@ -321,13 +312,11 @@ components: description: The type of connector. enum: - .gemini - examples: - - .gemini + example: .gemini name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_gemini' create_connector_request_cases_webhook: @@ -347,13 +336,11 @@ components: description: The type of connector. enum: - .cases-webhook - examples: - - .cases-webhook + example: .cases-webhook name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_cases_webhook' create_connector_request_d3security: @@ -374,13 +361,11 @@ components: description: The type of connector. enum: - .d3security - examples: - - .d3security + example: .d3security name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_d3security' create_connector_request_email: @@ -401,13 +386,11 @@ components: description: The type of connector. enum: - .email - examples: - - .email + example: .email name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_email' create_connector_request_genai: @@ -428,13 +411,11 @@ components: description: The type of connector. enum: - .gen-ai - examples: - - .gen-ai + example: .gen-ai name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_genai' create_connector_request_index: @@ -453,13 +434,11 @@ components: description: The type of connector. enum: - .index - examples: - - .index + example: .index name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector create_connector_request_jira: title: Create Jira connector request description: The Jira connector uses the REST API v2 to create Jira issues. @@ -477,13 +456,11 @@ components: description: The type of connector. enum: - .jira - examples: - - .jira + example: .jira name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_jira' create_connector_request_opsgenie: @@ -503,13 +480,11 @@ components: description: The type of connector. enum: - .opsgenie - examples: - - .opsgenie + example: .opsgenie name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_opsgenie' create_connector_request_pagerduty: @@ -530,13 +505,11 @@ components: description: The type of connector. enum: - .pagerduty - examples: - - .pagerduty + example: .pagerduty name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_pagerduty' create_connector_request_resilient: @@ -554,15 +527,13 @@ components: connector_type_id: description: The type of connector. type: string - examples: - - .resilient + example: .resilient enum: - .resilient name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_resilient' create_connector_request_sentinelone: @@ -584,13 +555,11 @@ components: description: The type of connector. enum: - .sentinelone - examples: - - .sentinelone + example: .sentinelone name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_sentinelone' create_connector_request_serverlog: @@ -606,13 +575,11 @@ components: description: The type of connector. enum: - .server-log - examples: - - .server-log + example: .server-log name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector create_connector_request_servicenow: title: Create ServiceNow ITSM connector request description: | @@ -631,13 +598,11 @@ components: description: The type of connector. enum: - .servicenow - examples: - - .servicenow + example: .servicenow name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_servicenow' create_connector_request_servicenow_itom: @@ -658,13 +623,11 @@ components: description: The type of connector. enum: - .servicenow-itom - examples: - - .servicenow-itom + example: .servicenow-itom name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_servicenow' create_connector_request_servicenow_sir: @@ -685,13 +648,11 @@ components: description: The type of connector. enum: - .servicenow-sir - examples: - - .servicenow-sir + example: .servicenow-sir name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_servicenow' create_connector_request_slack_api: @@ -710,13 +671,11 @@ components: description: The type of connector. enum: - .slack_api - examples: - - .slack_api + example: .slack_api name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_slack_api' create_connector_request_slack_webhook: @@ -733,13 +692,11 @@ components: description: The type of connector. enum: - .slack - examples: - - .slack + example: .slack name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_slack_webhook' create_connector_request_swimlane: @@ -759,13 +716,11 @@ components: description: The type of connector. enum: - .swimlane - examples: - - .swimlane + example: .swimlane name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_swimlane' create_connector_request_teams: @@ -782,13 +737,11 @@ components: description: The type of connector. enum: - .teams - examples: - - .teams + example: .teams name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_teams' create_connector_request_tines: @@ -809,13 +762,11 @@ components: description: The type of connector. enum: - .tines - examples: - - .tines + example: .tines name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_tines' create_connector_request_torq: @@ -836,13 +787,11 @@ components: description: The type of connector. enum: - .torq - examples: - - .torq + example: .torq name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_torq' create_connector_request_webhook: @@ -863,13 +812,11 @@ components: description: The type of connector. enum: - .webhook - examples: - - .webhook + example: .webhook name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_webhook' create_connector_request_xmatters: @@ -890,13 +837,11 @@ components: description: The type of connector. enum: - .xmatters - examples: - - .xmatters + example: .xmatters name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_xmatters' config_properties_bedrock: @@ -978,8 +923,7 @@ components: type: string description: | A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is `case.comment`. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. - examples: - - '{"body": {{{case.comment}}}}' + example: '{"body": {{{case.comment}}}}' createCommentMethod: type: string description: | @@ -993,14 +937,12 @@ components: type: string description: | The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts. - examples: - - https://example.com/issue/{{{external.system.id}}}/comment + example: https://example.com/issue/{{{external.system.id}}}/comment createIncidentJson: type: string description: | A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. - examples: - - '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' + example: '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' createIncidentMethod: type: string description: | @@ -1024,8 +966,7 @@ components: type: string description: | The REST API URL to get the case by ID from the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. - examples: - - https://example.com/issue/{{{external.system.id}}} + example: https://example.com/issue/{{{external.system.id}}} hasAuth: type: boolean description: If true, a username and password for login type authentication must be provided. @@ -1038,8 +979,7 @@ components: type: string description: | The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. - examples: - - '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' + example: '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' updateIncidentMethod: type: string description: | @@ -1053,14 +993,12 @@ components: type: string description: | The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. - examples: - - https://example.com/issue/{{{external.system.ID}}} + example: https://example.com/issue/{{{external.system.ID}}} viewIncidentUrl: type: string description: | The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL. - examples: - - https://testing-jira.atlassian.net/browse/{{{external.system.title}}} + example: https://testing-jira.atlassian.net/browse/{{{external.system.title}}} secrets_properties_cases_webhook: title: Connector secrets properties for Webhook - Case Management connector type: object @@ -1102,9 +1040,8 @@ components: clientId: description: | The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. - type: - - string - - 'null' + type: string + nullable: true from: description: | The from address for all emails sent by the connector. It must be specified in `user@host-name` format. @@ -1119,9 +1056,8 @@ components: The host name of the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. type: string oauthTokenUrl: - type: - - string - - 'null' + type: string + nullable: true port: description: | The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. @@ -1144,9 +1080,8 @@ components: tenantId: description: | The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. - type: - - string - - 'null' + type: string + nullable: true secrets_properties_email: title: Connector secrets properties for an email connector description: Defines secrets for connectors when type is `.email`. @@ -1230,9 +1165,8 @@ components: executionTimeField: description: A field that indicates when the document was indexed. default: null - type: - - string - - 'null' + type: string + nullable: true index: description: The Elasticsearch index to be written to. type: string @@ -1297,11 +1231,9 @@ components: properties: apiUrl: description: The PagerDuty event URL. - type: - - string - - 'null' - examples: - - https://events.pagerduty.com/v2/enqueue + type: string + nullable: true + example: https://events.pagerduty.com/v2/enqueue secrets_properties_pagerduty: title: Connector secrets properties for a PagerDuty connector description: Defines secrets for connectors when type is `.pagerduty`. @@ -1737,10 +1669,10 @@ components: properties: authType: type: string + nullable: true enum: - webhook-authentication-basic - webhook-authentication-ssl - - 'null' description: | The type of authentication to use: basic, SSL, or none. ca: @@ -1759,9 +1691,8 @@ components: description: | If `true`, a user name and password must be provided for login type authentication. headers: - type: - - object - - 'null' + type: object + nullable: true description: A set of key-value pairs sent as headers with the request. method: type: string @@ -1814,9 +1745,8 @@ components: configUrl: description: | The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`. - type: - - string - - 'null' + type: string + nullable: true usesBasic: description: Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`). type: boolean @@ -2299,9 +2229,8 @@ components: - name properties: config: - type: - - object - - 'null' + type: object + nullable: true connector_type_id: type: string description: The type of connector. @@ -2687,30 +2616,25 @@ components: is_deprecated: type: boolean description: Indicates whether the connector type is deprecated. - examples: - - false + example: false is_missing_secrets: type: boolean description: Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type. - examples: - - false + example: false is_preconfigured: type: boolean description: | Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. - examples: - - false + example: false is_system_action: type: boolean description: Indicates whether the connector is used for system actions. - examples: - - false + example: false referenced_by_count: type: integer description: | Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API. - examples: - - 2 + example: 2 connector_response_properties: title: Connector response properties description: The properties vary depending on the connector type. @@ -2806,8 +2730,7 @@ components: name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_cases_webhook' update_connector_request_d3security: @@ -3004,8 +2927,7 @@ components: name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: '#/components/schemas/secrets_properties_swimlane' update_connector_request_teams: @@ -3148,8 +3070,7 @@ components: - .torq - .webhook - .xmatters - examples: - - .server-log + example: .server-log examples: create_email_connector_request: summary: Create an email connector. @@ -3345,16 +3266,14 @@ components: properties: error: type: string - examples: - - Unauthorized + example: Unauthorized enum: - Unauthorized message: type: string statusCode: type: integer - examples: - - 401 + example: 401 enum: - 401 '404': @@ -3367,17 +3286,14 @@ components: properties: error: type: string - examples: - - Not Found + example: Not Found enum: - Not Found message: type: string - examples: - - Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found + example: Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found statusCode: type: integer - examples: - - 404 + example: 404 enum: - 404 diff --git a/x-pack/plugins/actions/docs/openapi/components/parameters/action_id.yaml b/x-pack/plugins/actions/docs/openapi/components/parameters/action_id.yaml index acbc6ab5acd63..3ee0b642c9dee 100644 --- a/x-pack/plugins/actions/docs/openapi/components/parameters/action_id.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/parameters/action_id.yaml @@ -4,5 +4,4 @@ description: An identifier for the action. required: true schema: type: string - examples: - - c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad + example: c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad diff --git a/x-pack/plugins/actions/docs/openapi/components/parameters/connector_id.yaml b/x-pack/plugins/actions/docs/openapi/components/parameters/connector_id.yaml index fdf1487e626a8..d98c2cec803ff 100644 --- a/x-pack/plugins/actions/docs/openapi/components/parameters/connector_id.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/parameters/connector_id.yaml @@ -4,5 +4,4 @@ description: An identifier for the connector. required: true schema: type: string - examples: - - df770e30-8b8b-11ed-a780-3b746c987a81 + example: df770e30-8b8b-11ed-a780-3b746c987a81 diff --git a/x-pack/plugins/actions/docs/openapi/components/parameters/space_id.yaml b/x-pack/plugins/actions/docs/openapi/components/parameters/space_id.yaml index 45787e844caec..0a9fba457e3e7 100644 --- a/x-pack/plugins/actions/docs/openapi/components/parameters/space_id.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/parameters/space_id.yaml @@ -4,5 +4,4 @@ description: An identifier for the space. If `/s/` and the identifier are omitte required: true schema: type: string - examples: - - default + example: default diff --git a/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml b/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml index 4f8890737ff40..263623dd1fb4c 100644 --- a/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml @@ -6,13 +6,10 @@ content: properties: error: type: string - examples: - - Bad Request + example: Bad Request message: type: string - examples: - - "error validating action type config: [index]: expected value of type [string] but got [undefined]" + example: "error validating action type config: [index]: expected value of type [string] but got [undefined]" statusCode: type: integer - examples: - - 400 \ No newline at end of file + example: 400 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/responses/401.yaml b/x-pack/plugins/actions/docs/openapi/components/responses/401.yaml index 78b77b3ab5f43..ff5cbfd4c2768 100644 --- a/x-pack/plugins/actions/docs/openapi/components/responses/401.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/responses/401.yaml @@ -7,15 +7,13 @@ content: properties: error: type: string - examples: - - Unauthorized + example: Unauthorized enum: - Unauthorized message: type: string statusCode: type: integer - examples: - - 401 + example: 401 enum: - 401 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/responses/404.yaml b/x-pack/plugins/actions/docs/openapi/components/responses/404.yaml index d4cf816f5903c..56964c6015c85 100644 --- a/x-pack/plugins/actions/docs/openapi/components/responses/404.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/responses/404.yaml @@ -7,17 +7,14 @@ content: properties: error: type: string - examples: - - Not Found + example: Not Found enum: - Not Found message: type: string - examples: - - "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" + example: "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" statusCode: type: integer - examples: - - 404 + example: 404 enum: - 404 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_cases_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_cases_webhook.yaml index a452a1fdfd060..b2a1ea8848ba7 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_cases_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_cases_webhook.yaml @@ -22,8 +22,7 @@ properties: connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. - examples: - - '{"body": {{{case.comment}}}}' + example: '{"body": {{{case.comment}}}}' createCommentMethod: type: string description: > @@ -41,8 +40,7 @@ properties: You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts. - examples: - - https://example.com/issue/{{{external.system.id}}}/comment + example: https://example.com/issue/{{{external.system.id}}}/comment createIncidentJson: type: string description: > @@ -54,8 +52,7 @@ properties: connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. - examples: - - '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' + example: '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' createIncidentMethod: type: string description: > @@ -89,8 +86,7 @@ properties: variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. - examples: - - https://example.com/issue/{{{external.system.id}}} + example: https://example.com/issue/{{{external.system.id}}} hasAuth: type: boolean description: If true, a username and password for login type authentication must be provided. @@ -111,8 +107,7 @@ properties: connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. - examples: - - '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' + example: '{"fields": {"summary": {{{case.title}}},"description": {{{case.description}}},"labels": {{{case.tags}}}}}' updateIncidentMethod: type: string description: > @@ -129,14 +124,12 @@ properties: The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. - examples: - - https://example.com/issue/{{{external.system.ID}}} + example: https://example.com/issue/{{{external.system.ID}}} viewIncidentUrl: type: string description: > The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL. - examples: - - https://testing-jira.atlassian.net/browse/{{{external.system.title}}} + example: https://testing-jira.atlassian.net/browse/{{{external.system.title}}} diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_email.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_email.yaml index 202f4022a6fbd..6d3618e2bba27 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_email.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_email.yaml @@ -8,9 +8,8 @@ properties: description: > The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. - type: - - "string" - - "null" + type: string + nullable: true from: description: > The from address for all emails sent by the connector. It must be specified in `user@host-name` format. @@ -28,9 +27,8 @@ properties: type: string oauthTokenUrl: # description: TBD - type: - - "string" - - "null" + type: string + nullable: true port: description: > The port to connect to on the service provider. @@ -57,6 +55,5 @@ properties: description: > The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. - type: - - "string" - - "null" \ No newline at end of file + type: string + nullable: true \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_index.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_index.yaml index f6d3af59b4937..6c335b166d20a 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_index.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_index.yaml @@ -7,9 +7,8 @@ properties: executionTimeField: description: A field that indicates when the document was indexed. default: null - type: - - "string" - - "null" + type: string + nullable: true index: description: The Elasticsearch index to be written to. type: string diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_pagerduty.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_pagerduty.yaml index bfbec7b46190b..562557f548ece 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_pagerduty.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_pagerduty.yaml @@ -4,8 +4,6 @@ type: object properties: apiUrl: description: The PagerDuty event URL. - type: - - "string" - - "null" - examples: - - https://events.pagerduty.com/v2/enqueue \ No newline at end of file + type: string + nullable: true + example: https://events.pagerduty.com/v2/enqueue \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml index 601d410666576..bf073419a4e09 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml @@ -4,10 +4,10 @@ type: object properties: authType: type: string + nullable: true enum: - webhook-authentication-basic - webhook-authentication-ssl - - "null" description: > The type of authentication to use: basic, SSL, or none. ca: @@ -27,9 +27,8 @@ properties: description: > If `true`, a user name and password must be provided for login type authentication. headers: - type: - - "object" - - "null" + type: object + nullable: true description: A set of key-value pairs sent as headers with the request. method: type: string diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_xmatters.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_xmatters.yaml index 3393c11ecd90d..350e96f3aa63d 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_xmatters.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_xmatters.yaml @@ -6,9 +6,8 @@ properties: description: > The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`. - type: - - "string" - - "null" + type: string + nullable: true usesBasic: description: Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`). type: boolean diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml index da741478864b4..a397e668102a6 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml @@ -8,9 +8,8 @@ required: - name properties: config: - type: - - "object" - - "null" + type: object + nullable: true connector_type_id: type: string description: The type of connector. diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml index f202efc087b00..db6262f04c010 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml @@ -26,5 +26,4 @@ enum: - .torq - .webhook - .xmatters -examples: - - .server-log \ No newline at end of file +example: .server-log \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml index e8feecb0051cd..2acc21bfbfac7 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml @@ -14,12 +14,10 @@ properties: description: The type of connector. enum: - .bedrock - examples: - - .bedrock + example: .bedrock name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_bedrock.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_cases_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_cases_webhook.yaml index 0cd030d740809..bcbe840c03513 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_cases_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_cases_webhook.yaml @@ -15,12 +15,10 @@ properties: description: The type of connector. enum: - .cases-webhook - examples: - - .cases-webhook + example: .cases-webhook name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_cases_webhook.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_d3security.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_d3security.yaml index 6b5389cc80f31..39cdda80b7dd2 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_d3security.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_d3security.yaml @@ -15,12 +15,10 @@ properties: description: The type of connector. enum: - .d3security - examples: - - .d3security + example: .d3security name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_d3security.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_email.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_email.yaml index 1f1c6c079770a..89f0b79c4e74b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_email.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_email.yaml @@ -18,12 +18,10 @@ properties: description: The type of connector. enum: - .email - examples: - - .email + example: .email name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_email.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_gemini.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_gemini.yaml index b9f4a651003c0..5b9cc31ae3787 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_gemini.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_gemini.yaml @@ -14,12 +14,10 @@ properties: description: The type of connector. enum: - .gemini - examples: - - .gemini + example: .gemini name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_gemini.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_genai.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_genai.yaml index 725f842f91093..95d65bdb80919 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_genai.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_genai.yaml @@ -16,12 +16,10 @@ properties: description: The type of connector. enum: - .gen-ai - examples: - - .gen-ai + example: .gen-ai name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_genai.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_index.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_index.yaml index ad8e9be9a41dc..26d6e118c1fe8 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_index.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_index.yaml @@ -13,10 +13,8 @@ properties: description: The type of connector. enum: - .index - examples: - - .index + example: .index name: type: string description: The display name for the connector. - examples: - - my-connector \ No newline at end of file + example: my-connector \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_jira.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_jira.yaml index 95ccaa5b2ec6f..5b6077e875b24 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_jira.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_jira.yaml @@ -14,12 +14,10 @@ properties: description: The type of connector. enum: - .jira - examples: - - .jira + example: .jira name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_jira.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_opsgenie.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_opsgenie.yaml index 51c29f5cdd8fd..6de1296dac43c 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_opsgenie.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_opsgenie.yaml @@ -14,12 +14,10 @@ properties: description: The type of connector. enum: - .opsgenie - examples: - - .opsgenie + example: .opsgenie name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_opsgenie.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_pagerduty.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_pagerduty.yaml index 66ffc61d30f30..498488299afd3 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_pagerduty.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_pagerduty.yaml @@ -16,12 +16,10 @@ properties: description: The type of connector. enum: - .pagerduty - examples: - - .pagerduty + example: .pagerduty name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_pagerduty.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_resilient.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_resilient.yaml index 60467336c0d9a..c3f766625b7da 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_resilient.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_resilient.yaml @@ -12,14 +12,12 @@ properties: connector_type_id: description: The type of connector. type: string - examples: - - .resilient + example: .resilient enum: - .resilient name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_resilient.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_sentinelone.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_sentinelone.yaml index d741f9b35af35..0d2809f24d78b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_sentinelone.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_sentinelone.yaml @@ -18,12 +18,10 @@ properties: description: The type of connector. enum: - .sentinelone - examples: - - .sentinelone + example: .sentinelone name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_sentinelone.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_serverlog.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_serverlog.yaml index 0cb85403663c6..eac0a0d65b69f 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_serverlog.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_serverlog.yaml @@ -10,10 +10,8 @@ properties: description: The type of connector. enum: - .server-log - examples: - - .server-log + example: .server-log name: type: string description: The display name for the connector. - examples: - - my-connector \ No newline at end of file + example: my-connector \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow.yaml index b0f35483cc39f..e03303dcada4f 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow.yaml @@ -16,12 +16,10 @@ properties: description: The type of connector. enum: - .servicenow - examples: - - .servicenow + example: .servicenow name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_servicenow.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_itom.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_itom.yaml index bfbeb231ca7dc..70a4c05c96522 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_itom.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_itom.yaml @@ -16,12 +16,10 @@ properties: description: The type of connector. enum: - .servicenow-itom - examples: - - .servicenow-itom + example: .servicenow-itom name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_servicenow.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_sir.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_sir.yaml index 37519eb63f27b..4d247c456f3e6 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_sir.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_servicenow_sir.yaml @@ -16,12 +16,10 @@ properties: description: The type of connector. enum: - .servicenow-sir - examples: - - .servicenow-sir + example: .servicenow-sir name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_servicenow.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_api.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_api.yaml index 2044087fba78c..3870f418606a2 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_api.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_api.yaml @@ -13,12 +13,10 @@ properties: description: The type of connector. enum: - .slack_api - examples: - - .slack_api + example: .slack_api name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_slack_api.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_webhook.yaml index 3e884daa6e3b8..1c046cc3f000c 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_slack_webhook.yaml @@ -11,12 +11,10 @@ properties: description: The type of connector. enum: - .slack - examples: - - .slack + example: .slack name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_slack_webhook.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_swimlane.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_swimlane.yaml index 633438a721ee9..3de4f5ecbccef 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_swimlane.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_swimlane.yaml @@ -14,12 +14,10 @@ properties: description: The type of connector. enum: - .swimlane - examples: - - .swimlane + example: .swimlane name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_swimlane.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_teams.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_teams.yaml index 787f057c09ce6..5e0d449bf5546 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_teams.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_teams.yaml @@ -11,12 +11,10 @@ properties: description: The type of connector. enum: - .teams - examples: - - .teams + example: .teams name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_teams.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_tines.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_tines.yaml index c5333c8acc479..224c3e03c4363 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_tines.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_tines.yaml @@ -15,12 +15,10 @@ properties: description: The type of connector. enum: - .tines - examples: - - .tines + example: .tines name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_tines.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_torq.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_torq.yaml index a4ab3cc92aa0d..934f9c9c1b395 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_torq.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_torq.yaml @@ -15,12 +15,10 @@ properties: description: The type of connector. enum: - .torq - examples: - - .torq + example: .torq name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_torq.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_webhook.yaml index 30e9663da8d99..e0ead115d48dc 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_webhook.yaml @@ -15,12 +15,10 @@ properties: description: The type of connector. enum: - .webhook - examples: - - .webhook + example: .webhook name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_webhook.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_xmatters.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_xmatters.yaml index 753888b16ae5e..13213d39561b2 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_xmatters.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_xmatters.yaml @@ -16,12 +16,10 @@ properties: description: The type of connector. enum: - .xmatters - examples: - - .xmatters + example: .xmatters name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_xmatters.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/is_deprecated.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/is_deprecated.yaml index ac0a26102eed1..75fb1efe2f589 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/is_deprecated.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/is_deprecated.yaml @@ -1,4 +1,3 @@ type: boolean description: Indicates whether the connector type is deprecated. -examples: - - false \ No newline at end of file +example: false \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/is_missing_secrets.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/is_missing_secrets.yaml index a7ad3f9542b3f..cad03a44f8629 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/is_missing_secrets.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/is_missing_secrets.yaml @@ -1,4 +1,3 @@ type: boolean description: Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type. -examples: - - false \ No newline at end of file +example: false \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml index d3f711c229399..e38741c83718e 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml @@ -2,5 +2,4 @@ type: boolean description: > Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. -examples: - - false \ No newline at end of file +example: false \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/is_system_action.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/is_system_action.yaml index 5a78f4676646f..fd0dd06ef5fff 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/is_system_action.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/is_system_action.yaml @@ -1,4 +1,3 @@ type: boolean description: Indicates whether the connector is used for system actions. -examples: - - false \ No newline at end of file +example: false \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml index 0a65bf9a854ff..61579fa3dc6ce 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml @@ -3,5 +3,4 @@ description: > Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API. -examples: - - 2 \ No newline at end of file +example: 2 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_params_trigger_pagerduty.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_params_trigger_pagerduty.yaml index 75a59af156264..71410725cbeae 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_params_trigger_pagerduty.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_params_trigger_pagerduty.yaml @@ -7,13 +7,11 @@ properties: class: description: The class or type of the event. type: string - examples: - - cpu load + example: cpu load component: description: The component of the source machine that is responsible for the event. type: string - examples: - - eth0 + example: eth0 customDetails: description: Additional details to add to the event. type: object @@ -31,8 +29,7 @@ properties: group: description: The logical grouping of components of a service. type: string - examples: - - app-stack + example: app-stack links: description: A list of links to add to the event. type: array diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_closeincident.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_closeincident.yaml index a53c4f90b226e..82f9a97a60412 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_closeincident.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_closeincident.yaml @@ -22,13 +22,15 @@ properties: - required: [externalId] properties: correlation_id: - type: ['null', string] + type: string + nullable: true description: > An identifier that is assigned to the incident when it is created by the connector. NOTE: If you use the default value and the rule generates multiple alerts that use the same alert IDs, the latest open incident for this correlation ID is closed unless you specify the external ID. maxLength: 100 default: '{{rule.id}}:{{alert.id}}' externalId: - type: ['null', string] + type: string + nullable: true description: The unique identifier (`incidentId`) for the incident in ServiceNow. \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_createalert.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_createalert.yaml index a53560951361f..e739a9ed6c91d 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_createalert.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_createalert.yaml @@ -30,8 +30,7 @@ properties: type: object description: The custom properties of the alert. additionalProperties: true - examples: - - {"key1":"value1","key2":"value2"} + example: {"key1":"value1","key2":"value2"} entity: type: string description: The domain of the alert. For example, the application or server name. diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_fieldsbyissuetype.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_fieldsbyissuetype.yaml index 6c39957c29fc4..e8c8869e7d68b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_fieldsbyissuetype.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_fieldsbyissuetype.yaml @@ -18,6 +18,5 @@ properties: id: type: string description: The Jira issue type identifier. - examples: - - 10024 + example: 10024 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_getincident.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_getincident.yaml index 7a16f3d9f8295..666c0257f68b8 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_getincident.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_getincident.yaml @@ -18,5 +18,4 @@ properties: externalId: type: string description: The Jira, ServiceNow ITSM, or ServiceNow SecOps issue identifier. - examples: - - 71778 + example: 71778 diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_issue.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_issue.yaml index 3743e7fa90bd3..56ee923b40063 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_issue.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_subaction_issue.yaml @@ -17,5 +17,4 @@ properties: id: type: string description: The Jira issue identifier. - examples: - - 71778 \ No newline at end of file + example: 71778 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_cases_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_cases_webhook.yaml index 9201a1b1e1d70..66250b31a94eb 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_cases_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_cases_webhook.yaml @@ -9,7 +9,6 @@ properties: name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_cases_webhook.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_swimlane.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_swimlane.yaml index 771625841a042..81321351b74ec 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_swimlane.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_swimlane.yaml @@ -10,7 +10,6 @@ properties: name: type: string description: The display name for the connector. - examples: - - my-connector + example: my-connector secrets: $ref: 'secrets_properties_swimlane.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/entrypoint.yaml b/x-pack/plugins/actions/docs/openapi/entrypoint.yaml index d082d91a2a4e5..ba61b00c3c737 100644 --- a/x-pack/plugins/actions/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/actions/docs/openapi/entrypoint.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Connectors description: OpenAPI schema for Connectors endpoints @@ -14,16 +14,6 @@ tags: servers: - url: / paths: - '/api/actions/connector': - $ref: 'paths/api@actions@connector.yaml' - '/api/actions/connector/{connectorId}': - $ref: 'paths/api@actions@connector@{connectorid}.yaml' - '/api/actions/connector/{connectorId}/_execute': - $ref: paths/api@actions@connector@{connectorid}@_execute.yaml - '/api/actions/connectors': - $ref: paths/api@actions@connectors.yaml - '/api/actions/connector_types': - $ref: paths/api@actions@connector_types.yaml '/s/{spaceId}/api/actions/connector': $ref: 'paths/s@{spaceid}@api@actions@connector.yaml' '/s/{spaceId}/api/actions/connector/{connectorId}': @@ -34,6 +24,17 @@ paths: $ref: paths/s@{spaceid}@api@actions@connector_types.yaml '/s/{spaceId}/api/actions/connector/{connectorId}/_execute': $ref: paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml +# Default space + '/api/actions/connector': + $ref: 'paths/api@actions@connector.yaml' + '/api/actions/connector/{connectorId}': + $ref: 'paths/api@actions@connector@{connectorid}.yaml' + '/api/actions/connector/{connectorId}/_execute': + $ref: paths/api@actions@connector@{connectorid}@_execute.yaml + '/api/actions/connectors': + $ref: paths/api@actions@connectors.yaml + '/api/actions/connector_types': + $ref: paths/api@actions@connector_types.yaml # Deprecated endpoints: '/s/{spaceId}/api/actions/action/{actionId}': $ref: 'paths/s@{spaceid}@api@actions@action@{actionid}.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml b/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml index 4780a65da6520..60cca6f18bc44 100644 --- a/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml +++ b/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml @@ -1,4 +1,4 @@ -openapi: 3.1.0 +openapi: 3.0.3 info: title: Connectors description: OpenAPI schema for connectors in Serverless projects @@ -31,6 +31,9 @@ components: type: apiKey in: header name: Authorization - description: 'e.g. Authorization: ApiKey base64AccessApiKey' + description: > + Serverless APIs support only key-based authentication. + You must create an API key and use the encoded value in the request header. + For example: 'Authorization: ApiKey base64AccessApiKey'. security: - apiKeyAuth: [] diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml index c6634bb6ea532..5f82202bed534 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml @@ -1,5 +1,5 @@ post: - summary: Creates a connector. + summary: Create a connector operationId: createConnector tags: - connectors diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml index 6464b9592436a..c9b4c269e6cc2 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a connector by ID. + summary: Get a connector information operationId: getConnector tags: - connectors @@ -21,7 +21,7 @@ get: $ref: '../components/responses/404.yaml' delete: - summary: Deletes a connector. + summary: Delete a connector operationId: deleteConnector tags: - connectors @@ -37,7 +37,7 @@ delete: $ref: '../components/responses/404.yaml' post: - summary: Creates a connector. + summary: Create a connector operationId: createConnectorId tags: - connectors @@ -51,8 +51,7 @@ post: required: true schema: type: string - examples: - - ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 requestBody: required: true content: @@ -76,7 +75,7 @@ post: $ref: '../components/responses/401.yaml' put: - summary: Updates the attributes for a connector. + summary: Update a connector operationId: updateConnector tags: - connectors diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml index 6d4de54cda3bc..93037c6d21779 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml @@ -1,5 +1,5 @@ post: - summary: Runs a connector. + summary: Run a connector operationId: runConnector description: > You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml index 94dbb727eea4a..3284d79cd9a49 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a list of all connector types. + summary: Get all connector types operationId: getConnectorTypes tags: - connectors @@ -24,41 +24,34 @@ get: enabled: type: boolean description: Indicates whether the connector type is enabled in Kibana. - examples: - - true + example: true enabled_in_config: type: boolean description: Indicates whether the connector type is enabled in the Kibana configuration file. - examples: - - true + example: true enabled_in_license: type: boolean description: Indicates whether the connector is enabled in the license. - examples: - - true + example: true id: $ref: '../components/schemas/connector_types.yaml' is_system_action_type: type: boolean - examples: - - false + example: false minimum_license_required: type: string description: The license that is required to use the connector type. - examples: - - basic + example: basic name: type: string description: The name of the connector type. - examples: - - Index + example: Index supported_feature_ids: type: array description: The features that are supported by the connector type. items: $ref: '../components/schemas/features.yaml' - examples: - - [alerting, cases, siem] + example: [alerting, cases, siem] examples: getConnectorTypesServerlessResponse: $ref: '../components/examples/get_connector_types_generativeai_response.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml index 82b83651644e7..b94954173e22e 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves all connectors. + summary: Get all connectors operationId: getConnectors tags: - connectors diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml index aad5ca61ac3be..94aa1f5c420a1 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves all connectors. + summary: Get all connectors operationId: legacyGetConnectors deprecated: true description: Deprecated in 7.13.0. Use the get all connectors API instead. @@ -20,7 +20,7 @@ get: $ref: '../components/responses/401.yaml' post: - summary: Creates a connector. + summary: Create a connector operationId: legacyCreateConnector deprecated: true description: Deprecated in 7.13.0. Use the create connector API instead. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml index dcf7a2759a35a..f2a5f62516aba 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml @@ -1,5 +1,5 @@ delete: - summary: Deletes a connector. + summary: Delete a connector operationId: legacyDeleteConnector deprecated: true description: > @@ -18,7 +18,7 @@ delete: $ref: '../components/responses/401.yaml' get: - summary: Retrieves a connector by ID. + summary: Get connector information operationId: legacyGetConnector description: Deprecated in 7.13.0. Use the get connector API instead. deprecated: true @@ -34,7 +34,7 @@ get: $ref: '../components/responses/401.yaml' put: - summary: Updates the attributes for a connector. + summary: Update a connector operationId: legacyUpdateConnector deprecated: true description: Deprecated in 7.13.0. Use the update connector API instead. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml index 9fe5cedda84de..1d1db3f341e52 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml @@ -1,5 +1,5 @@ post: - summary: Runs a connector. + summary: Run a connector operationId: legacyRunConnector deprecated: true description: Deprecated in 7.13.0. Use the run connector API instead. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml index f116a699ed868..749647e8b9ce5 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml @@ -1,5 +1,5 @@ post: - summary: Creates a connector. + summary: Create a connector operationId: createConnectorWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml index 27351f0954eee..d4511a486c0e1 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a connector by ID. + summary: Get connector information operationId: getConnectorWithSpaceId description: > You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. @@ -24,7 +24,7 @@ get: $ref: '../components/responses/404.yaml' delete: - summary: Deletes a connector. + summary: Delete a connector operationId: deleteConnectorWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. @@ -44,7 +44,7 @@ delete: $ref: '../components/responses/404.yaml' post: - summary: Creates a connector. + summary: Create a connector operationId: createConnectorIdWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. @@ -59,8 +59,7 @@ post: required: true schema: type: string - examples: - - ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 requestBody: required: true content: @@ -84,7 +83,7 @@ post: $ref: '../components/responses/401.yaml' put: - summary: Updates the attributes for a connector. + summary: Update a connector operationId: updateConnectorWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml index 507194f31c380..76a30f54bab80 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml @@ -1,5 +1,5 @@ post: - summary: Runs a connector. + summary: Run a connector operationId: runConnectorWithSpaceId description: > You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml index 9a0fababdf166..88fbc1612e507 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a list of all connector types. + summary: Get all connector types operationId: getConnectorTypesWithSpaceId description: > You do not need any Kibana feature privileges to run this API. @@ -27,37 +27,31 @@ get: enabled: type: boolean description: Indicates whether the connector type is enabled in Kibana. - examples: - - true + example: true enabled_in_config: type: boolean description: Indicates whether the connector type is enabled in the Kibana `.yml` file. - examples: - - true + example: true enabled_in_license: type: boolean description: Indicates whether the connector is enabled in the license. - examples: - - true + example: true id: $ref: '../components/schemas/connector_types.yaml' minimum_license_required: type: string description: The license that is required to use the connector type. - examples: - - basic + example: basic name: type: string description: The name of the connector type. - examples: - - Index + example: Index supported_feature_ids: type: array description: The Kibana features that are supported by the connector type. items: $ref: '../components/schemas/features.yaml' - examples: - - [alerting, uptime, siem] + example: [alerting, uptime, siem] examples: getConnectorTypesResponse: $ref: '../components/examples/get_connector_types_response.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml index 7670187845710..3913919998e98 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves all connectors. + summary: Get all connectors operationId: getConnectorsWithSpaceId description: > You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml index 6bc2b9e5e53a8..daea4ed5219eb 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml @@ -1,5 +1,5 @@ get: - summary: Retrieves a list of all connector types. + summary: Get connector types operationId: legacyGetConnectorTypes deprecated: true description: Deprecated in 7.13.0. Use the get all connector types API instead. @@ -28,8 +28,7 @@ get: enabledInLicense: type: boolean description: Indicates whether the connector is enabled in the license. - examples: - - true + example: true id: type: string description: The unique identifier for the connector type. From 74903c349c03e610892636fe055eae51ab34b35e Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:56:22 -0400 Subject: [PATCH 076/127] [Security Solution][Endpoint] Fix automated response actions so that they only execute on alerts generated by `agent.type` of `endpoint` (#186333) ## Summary Fixes Automated Response actions so that they are only executed on alerts generated from Elastic Defend. For a background as to why this fix was needed, [see this comment here](https://github.com/elastic/kibana/issues/180774#issuecomment-2139526239). --- ...dule_notification_response_actions.test.ts | 24 +++++++++++++++++-- .../schedule_notification_response_actions.ts | 14 ++++++++--- .../rule_response_actions/types.ts | 1 + 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts index 6fac2725754d5..4dccc9ad0aae7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts @@ -14,7 +14,7 @@ import { responseActionsClientMock } from '../../../endpoint/services/actions/cl describe('ScheduleNotificationResponseActions', () => { const signalOne = { - agent: { id: 'agent-id-1' }, + agent: { id: 'agent-id-1', type: 'endpoint' }, _id: 'alert-id-1', user: { id: 'S-1-5-20' }, process: { @@ -23,7 +23,7 @@ describe('ScheduleNotificationResponseActions', () => { [ALERT_RULE_UUID]: 'rule-id-1', [ALERT_RULE_NAME]: 'rule-name-1', }; - const signalTwo = { agent: { id: 'agent-id-2' }, _id: 'alert-id-2' }; + const signalTwo = { agent: { id: 'agent-id-2', type: 'endpoint' }, _id: 'alert-id-2' }; const getSignals = () => [signalOne, signalTwo]; const osqueryActionMock = { @@ -210,5 +210,25 @@ describe('ScheduleNotificationResponseActions', () => { } ); }); + + it('should only attempt to send response actions to alerts from endpoint', async () => { + const signals = getSignals(); + signals.push({ agent: { id: '123-432', type: 'filebeat' }, _id: '1' }); + const responseActions: RuleResponseAction[] = [ + { + actionTypeId: ResponseActionTypesEnum['.endpoint'], + params: { + command: 'isolate', + comment: 'test process comment', + }, + }, + ]; + await scheduleNotificationResponseActions({ + signals, + responseActions, + }); + + expect(mockedResponseActionsClient.isolate).toHaveBeenCalledTimes(signals.length - 1); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts index d20995291b5f1..2fcf09d6cfbb4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts @@ -37,9 +37,17 @@ export const getScheduleNotificationResponseActionsService = }); } if (responseAction.actionTypeId === ResponseActionTypesEnum['.endpoint']) { - await endpointResponseAction(responseAction, endpointAppContextService, { - alerts, - }); + // We currently support only automated response actions for Elastic Defend. This will + // need to be updated once we introduce support for other EDR systems. + // For an explanation of why this is needed, see this comment here: + // https://github.com/elastic/kibana/issues/180774#issuecomment-2139526239 + const alertsFromElasticDefend = alerts.filter((alert) => alert.agent.type === 'endpoint'); + + if (alertsFromElasticDefend.length > 0) { + await endpointResponseAction(responseAction, endpointAppContextService, { + alerts: alertsFromElasticDefend, + }); + } } }) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/types.ts index d34d2eba9e5ab..e7317acfd7ca1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/types.ts @@ -24,6 +24,7 @@ export type Alert = ParsedTechnicalFields & { export interface AlertAgent { id: string; name: string; + type: string; } export interface AlertWithAgent extends Alert { From 793d96ee00fd5c229286d60d292cdd277e322ef4 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 18 Jun 2024 20:58:27 +0200 Subject: [PATCH 077/127] [Rule Management] Skip Cypress tests on MKI executions (#186122) ## Summary The `x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts` test is failing on MKI environments (the periodic pipeline). This is because the test in order to work need to have a feature flag enabled. FF are not currently supported on MKI environments, that is why in this PR we are skipping it from MKI environments by adding `@skipInServerlessMKI` label to it. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../rule_management/rule_details/backfill_group.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts index 1b2cbd9add957..7413b8a8f02c7 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts @@ -34,7 +34,7 @@ import { describe( 'Backfill groups', { - tags: ['@ess', '@serverless'], + tags: ['@ess', '@serverless', '@skipInServerlessMKI'], env: { ftrConfig: { kbnServerArgs: [ From f93f04a4ede23cebc90c36274443caa7945968f8 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 18 Jun 2024 15:39:31 -0400 Subject: [PATCH 078/127] [Fleet] Make enrollment settings API space aware (#186322) --- .../common/types/models/package_policy.ts | 1 + .../fleet/common/types/rest_spec/settings.ts | 1 + .../enrollment_settings_handler.test.ts | 3 + .../settings/enrollment_settings_handler.ts | 11 +- .../fleet/server/routes/setup/handlers.ts | 3 +- .../fleet/server/services/agent_policy.ts | 15 +- .../services/fleet_server/index.test.ts | 13 +- .../server/services/fleet_server/index.ts | 33 ++-- .../fleet/server/services/package_policy.ts | 4 +- .../server/services/package_policy_service.ts | 2 +- .../apis/space_awareness/api_helper.ts | 34 ++++ .../space_awareness/enrollment_settings.ts | 161 ++++++++++++++++++ .../apis/space_awareness/index.js | 1 + 13 files changed, 257 insertions(+), 25 deletions(-) create mode 100644 x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_settings.ts diff --git a/x-pack/plugins/fleet/common/types/models/package_policy.ts b/x-pack/plugins/fleet/common/types/models/package_policy.ts index c50c06b890ea1..1b8a407ff8dd9 100644 --- a/x-pack/plugins/fleet/common/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/package_policy.ts @@ -99,6 +99,7 @@ export interface UpdatePackagePolicy extends NewPackagePolicy { // SO definition for this type is declared in server/types/interfaces export interface PackagePolicy extends Omit { id: string; + spaceId?: string; inputs: PackagePolicyInput[]; version?: string; agents?: number; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/settings.ts b/x-pack/plugins/fleet/common/types/rest_spec/settings.ts index 33abccbc88e74..73ad6a3a219fc 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/settings.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/settings.ts @@ -34,6 +34,7 @@ export type EnrollmentSettingsFleetServerPolicy = Pick< | 'has_fleet_server' | 'fleet_server_host_id' | 'download_source_id' + | 'space_id' >; export interface GetEnrollmentSettingsResponse { diff --git a/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.test.ts b/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.test.ts index b41debffb3e6b..0a39101db8481 100644 --- a/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.test.ts +++ b/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.test.ts @@ -16,6 +16,9 @@ jest.mock('../../services', () => ({ get: jest.fn(), getByIDs: jest.fn(), }, + appContextService: { + getInternalUserSOClientWithoutSpaceExtension: jest.fn(), + }, downloadSourceService: { list: jest.fn().mockResolvedValue({ items: [ diff --git a/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.ts b/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.ts index 1662fed3fc31b..132777867becb 100644 --- a/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.ts +++ b/x-pack/plugins/fleet/server/routes/settings/enrollment_settings_handler.ts @@ -18,7 +18,7 @@ import type { } from '../../../common/types'; import type { FleetRequestHandler, GetEnrollmentSettingsRequestSchema } from '../../types'; import { defaultFleetErrorHandler } from '../../errors'; -import { agentPolicyService, downloadSourceService } from '../../services'; +import { agentPolicyService, appContextService, downloadSourceService } from '../../services'; import { getFleetServerHostsForAgentPolicy } from '../../services/fleet_server_host'; import { getFleetProxy } from '../../services/fleet_proxies'; import { getFleetServerPolicies, hasFleetServersForPolicies } from '../../services/fleet_server'; @@ -53,8 +53,8 @@ export const getEnrollmentSettingsHandler: FleetRequestHandler< settingsResponse.fleet_server.policies = fleetServerPolicies; settingsResponse.fleet_server.has_active = await hasFleetServersForPolicies( esClient, - soClient, - fleetServerPolicies.map((p) => p.id), + appContextService.getInternalUserSOClientWithoutSpaceExtension(), + fleetServerPolicies, true ); } @@ -115,6 +115,7 @@ export const getFleetServerOrAgentPolicies = async ( has_fleet_server: policy.has_fleet_server, fleet_server_host_id: policy.fleet_server_host_id, download_source_id: policy.download_source_id, + space_id: policy.space_id, }); // If an agent policy is specified, return only that policy @@ -136,7 +137,9 @@ export const getFleetServerOrAgentPolicies = async ( } // If an agent policy is not specified, return all fleet server policies - const fleetServerPolicies = (await getFleetServerPolicies(soClient)).map(mapPolicy); + const fleetServerPolicies = ( + await getFleetServerPolicies(appContextService.getInternalUserSOClientWithoutSpaceExtension()) + ).map(mapPolicy); return { fleetServerPolicies }; }; diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.ts index 58555f233142a..019fb2af5276b 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.ts @@ -16,10 +16,9 @@ import { isSecretStorageEnabled } from '../../services/secrets'; export const getFleetStatusHandler: FleetRequestHandler = async (context, request, response) => { const coreContext = await context.core; - const fleetContext = await context.fleet; const esClient = coreContext.elasticsearch.client.asInternalUser; - const soClient = fleetContext.internalSoClient; + const soClient = appContextService.getInternalUserSOClientWithoutSpaceExtension(); try { const isApiKeysEnabled = await appContextService diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index d3d94fa581955..029352e145ca6 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -414,10 +414,20 @@ class AgentPolicyService { public async getByIDs( soClient: SavedObjectsClientContract, - ids: string[], + ids: Array, options: { fields?: string[]; withPackagePolicies?: boolean; ignoreMissing?: boolean } = {} ): Promise { - const objects = ids.map((id) => ({ ...options, id, type: SAVED_OBJECT_TYPE })); + const objects = ids.map((id) => { + if (typeof id === 'string') { + return { ...options, id, type: SAVED_OBJECT_TYPE }; + } + return { + ...options, + id: id.id, + namespaces: id.spaceId ? [id.spaceId] : undefined, + type: SAVED_OBJECT_TYPE, + }; + }); const bulkGetResponse = await soClient.bulkGet(objects); const agentPolicies = await pMap( @@ -432,7 +442,6 @@ class AgentPolicyService { throw new FleetError(agentPolicySO.error.message); } } - const agentPolicy = mapAgentPolicySavedObjectToAgentPolicy(agentPolicySO); if (options.withPackagePolicies) { const agentPolicyWithPackagePolicies = await this.get( diff --git a/x-pack/plugins/fleet/server/services/fleet_server/index.test.ts b/x-pack/plugins/fleet/server/services/fleet_server/index.test.ts index 0a4ce31504383..f00d78cd59ad9 100644 --- a/x-pack/plugins/fleet/server/services/fleet_server/index.test.ts +++ b/x-pack/plugins/fleet/server/services/fleet_server/index.test.ts @@ -130,6 +130,7 @@ describe('getFleetServerPolicies', () => { version: '1.0.0', }, policy_id: 'fs-policy-1', + policy_ids: ['fs-policy-1'], }, { id: 'package-policy-2', @@ -140,6 +141,7 @@ describe('getFleetServerPolicies', () => { version: '1.0.0', }, policy_id: 'fs-policy-2', + policy_ids: ['fs-policy-2'], }, { id: 'package-policy-3', @@ -150,6 +152,7 @@ describe('getFleetServerPolicies', () => { version: '1.0.0', }, policy_id: 'agent-policy-2', + policy_ids: ['agent-policy-2'], }, ]; const mockFleetServerPolicies = [ @@ -218,7 +221,7 @@ describe('hasActiveFleetServersForPolicies', () => { const hasFs = await hasFleetServersForPolicies( mockEsClient, mockSoClient, - ['policy-1'], + [{ id: 'policy-1' }], true ); expect(hasFs).toBe(true); @@ -241,7 +244,7 @@ describe('hasActiveFleetServersForPolicies', () => { const hasFs = await hasFleetServersForPolicies( mockEsClient, mockSoClient, - ['policy-1'], + [{ id: 'policy-1' }], true ); expect(hasFs).toBe(true); @@ -264,7 +267,7 @@ describe('hasActiveFleetServersForPolicies', () => { const hasFs = await hasFleetServersForPolicies( mockEsClient, mockSoClient, - ['policy-1'], + [{ id: 'policy-1' }], true ); expect(hasFs).toBe(false); @@ -286,7 +289,9 @@ describe('hasActiveFleetServersForPolicies', () => { online: 0, error: 0, }); - const hasFs = await hasFleetServersForPolicies(mockEsClient, mockSoClient, ['policy-1']); + const hasFs = await hasFleetServersForPolicies(mockEsClient, mockSoClient, [ + { id: 'policy-1' }, + ]); expect(hasFs).toBe(true); }); }); diff --git a/x-pack/plugins/fleet/server/services/fleet_server/index.ts b/x-pack/plugins/fleet/server/services/fleet_server/index.ts index 88ba7ccc710d5..004a0deeea7b7 100644 --- a/x-pack/plugins/fleet/server/services/fleet_server/index.ts +++ b/x-pack/plugins/fleet/server/services/fleet_server/index.ts @@ -6,15 +6,15 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import semverGte from 'semver/functions/gte'; import semverCoerce from 'semver/functions/coerce'; +import { uniqBy } from 'lodash'; import type { AgentPolicy } from '../../../common/types'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE, FLEET_SERVER_PACKAGE } from '../../../common/constants'; - import { SO_SEARCH_LIMIT } from '../../constants'; import { getAgentsByKuery, getAgentStatusById } from '../agents'; - import { packagePolicyService } from '../package_policy'; import { agentPolicyService } from '../agent_policy'; import { getAgentStatusForAgentPolicy } from '../agents'; @@ -28,16 +28,20 @@ export const getFleetServerPolicies = async ( ): Promise => { const fleetServerPackagePolicies = await packagePolicyService.list(soClient, { kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${FLEET_SERVER_PACKAGE}`, + spaceId: '*', }); // Extract associated fleet server agent policy IDs - const fleetServerAgentPolicyIds = [ - ...new Set(fleetServerPackagePolicies.items.flatMap((p) => p.policy_ids)), - ]; + const fleetServerAgentPolicyIds = fleetServerPackagePolicies.items.flatMap((p) => + p.policy_ids?.map((id) => ({ id, spaceId: p.spaceId } ?? [])) + ); // Retrieve associated agent policies const fleetServerAgentPolicies = fleetServerAgentPolicyIds.length - ? await agentPolicyService.getByIDs(soClient, fleetServerAgentPolicyIds) + ? await agentPolicyService.getByIDs( + soClient, + uniqBy(fleetServerAgentPolicyIds, (p) => `${p?.spaceId ?? ''}:${p.id}`) + ) : []; return fleetServerAgentPolicies; @@ -51,15 +55,24 @@ export const getFleetServerPolicies = async ( export const hasFleetServersForPolicies = async ( esClient: ElasticsearchClient, soClient: SavedObjectsClientContract, - agentPolicyIds: string[], + agentPolicies: Array>, activeOnly: boolean = false ): Promise => { - if (agentPolicyIds.length > 0) { + if (agentPolicies.length > 0) { const agentStatusesRes = await getAgentStatusForAgentPolicy( esClient, soClient, undefined, - agentPolicyIds.map((id) => `policy_id:${id}`).join(' or ') + agentPolicies + .map(({ id, space_id: spaceId }) => { + const space = + spaceId && spaceId !== DEFAULT_SPACE_ID + ? `namespaces:"${spaceId}"` + : `not namespaces:* or namespaces:"${DEFAULT_SPACE_ID}"`; + + return `(policy_id:${id} and (${space}))`; + }) + .join(' or ') ); return activeOnly @@ -79,7 +92,7 @@ export async function hasFleetServers( return await hasFleetServersForPolicies( esClient, soClient, - (await getFleetServerPolicies(soClient)).map((policy) => policy.id) + await getFleetServerPolicies(soClient) ); } diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index cae84f2c8f5b1..dd4d26e28ca7e 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -726,7 +726,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { public async list( soClient: SavedObjectsClientContract, - options: ListWithKuery + options: ListWithKuery & { spaceId?: string } ): Promise> { const { page = 1, perPage = 20, sortField = 'updated_at', sortOrder = 'desc', kuery } = options; @@ -737,6 +737,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { page, perPage, filter: kuery ? normalizeKuery(SAVED_OBJECT_TYPE, kuery) : undefined, + namespaces: options.spaceId ? [options.spaceId] : undefined, }); for (const packagePolicy of packagePolicies?.saved_objects ?? []) { @@ -752,6 +753,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { id: packagePolicySO.id, version: packagePolicySO.version, ...packagePolicySO.attributes, + spaceId: packagePolicySO.namespaces?.[0], })), total: packagePolicies?.total, page, diff --git a/x-pack/plugins/fleet/server/services/package_policy_service.ts b/x-pack/plugins/fleet/server/services/package_policy_service.ts index 56e68537afb7e..5f5e775bf910a 100644 --- a/x-pack/plugins/fleet/server/services/package_policy_service.ts +++ b/x-pack/plugins/fleet/server/services/package_policy_service.ts @@ -105,7 +105,7 @@ export interface PackagePolicyClient { list( soClient: SavedObjectsClientContract, - options: ListWithKuery + options: ListWithKuery & { spaceId?: string } ): Promise>; listIds( diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts index cff3d3ddb637b..4b166d040625b 100644 --- a/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/api_helper.ts @@ -19,6 +19,7 @@ import { GetOneEnrollmentAPIKeyResponse, PostEnrollmentAPIKeyResponse, PostEnrollmentAPIKeyRequest, + GetEnrollmentSettingsResponse, } from '@kbn/fleet-plugin/common/types'; import { GetUninstallTokenResponse, @@ -30,6 +31,15 @@ export class SpaceTestApiClient { private getBaseUrl(spaceId?: string) { return spaceId ? `/s/${spaceId}` : ''; } + async setup(spaceId?: string): Promise { + const { body: res } = await this.supertest + .post(`${this.getBaseUrl(spaceId)}/api/fleet/setup`) + .set('kbn-xsrf', 'xxxx') + .send({}) + .expect(200); + + return res; + } // Agent policies async createAgentPolicy(spaceId?: string): Promise { const { body: res } = await this.supertest @@ -45,6 +55,22 @@ export class SpaceTestApiClient { return res; } + async createFleetServerPolicy(spaceId?: string): Promise { + const { body: res } = await this.supertest + .post(`${this.getBaseUrl(spaceId)}/api/fleet/agent_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `test ${uuidV4()}`, + description: '', + namespace: 'default', + inactivity_timeout: 24 * 1000, + has_fleet_server: true, + force: true, + }) + .expect(200); + + return res; + } async deleteAgentPolicy(agentPolicyId: string, spaceId?: string) { await this.supertest .post(`${this.getBaseUrl(spaceId)}/api/fleet/agent_policies/delete`) @@ -139,4 +165,12 @@ export class SpaceTestApiClient { return res; } + // Enrollment Settings + async getEnrollmentSettings(spaceId?: string): Promise { + const { body: res } = await this.supertest + .get(`${this.getBaseUrl(spaceId)}/internal/fleet/settings/enrollment`) + .expect(200); + + return res; + } } diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_settings.ts b/x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_settings.ts new file mode 100644 index 0000000000000..d5eb41afb2104 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/enrollment_settings.ts @@ -0,0 +1,161 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { SpaceTestApiClient } from './api_helper'; +import { cleanFleetIndices } from './helpers'; +import { setupTestSpaces, TEST_SPACE_1 } from './space_helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esClient = getService('es'); + const kibanaServer = getService('kibanaServer'); + const createFleetAgent = async (agentPolicyId: string, spaceId?: string) => { + const agentResponse = await esClient.index({ + index: '.fleet-agents', + refresh: true, + body: { + access_api_key_id: 'api-key-3', + active: true, + policy_id: agentPolicyId, + policy_revision_idx: 1, + last_checkin_status: 'online', + type: 'PERMANENT', + local_metadata: { + host: { hostname: 'host123' }, + elastic: { agent: { version: '8.15.0' } }, + }, + user_provided_metadata: {}, + enrolled_at: new Date().toISOString(), + last_checkin: new Date().toISOString(), + tags: ['tag1'], + namespaces: spaceId ? [spaceId] : undefined, + }, + }); + + return agentResponse._id; + }; + describe('enrollment_settings', async function () { + skipIfNoDockerRegistry(providerContext); + const apiClient = new SpaceTestApiClient(supertest); + + describe('Without Fleet server setup', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + + before(async () => { + await apiClient.setup(); + }); + + describe('GET /enrollments/settings', () => { + it('in default space it should not return an active fleet server', async () => { + const res = await apiClient.getEnrollmentSettings(); + expect(res.fleet_server.has_active).to.be(false); + }); + + it('in a specific spaceit should not return an active fleet server', async () => { + const res = await apiClient.getEnrollmentSettings(TEST_SPACE_1); + expect(res.fleet_server.has_active).to.be(false); + }); + }); + }); + + describe('With Fleet server setup in a specific space', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + + before(async () => { + await apiClient.setup(); + const testSpaceFleetServerPolicy = await apiClient.createFleetServerPolicy(TEST_SPACE_1); + await createFleetAgent(testSpaceFleetServerPolicy.item.id, TEST_SPACE_1); + }); + + describe('GET /enrollments/settings', () => { + it('in default space it should return all policies and active fleet server', async () => { + const res = await apiClient.getEnrollmentSettings(); + expect(res.fleet_server.has_active).to.be(true); + }); + + it('in a specific space it should return all policies and active fleet server', async () => { + const res = await apiClient.getEnrollmentSettings(TEST_SPACE_1); + expect(res.fleet_server.has_active).to.be(true); + }); + }); + }); + + describe('With Fleet server setup in default space', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.savedObjects.cleanStandardList({ + space: TEST_SPACE_1, + }); + await cleanFleetIndices(esClient); + }); + + setupTestSpaces(providerContext); + + before(async () => { + await apiClient.setup(); + const defaultFleetServerPolicy = await apiClient.createFleetServerPolicy(); + await createFleetAgent(defaultFleetServerPolicy.item.id); + }); + + describe('GET /enrollments/settings', () => { + it('in default space it should return all policies and active fleet server', async () => { + const res = await apiClient.getEnrollmentSettings(); + expect(res.fleet_server.has_active).to.be(true); + }); + + it('in a specific space it should return all policies and active fleet server', async () => { + const res = await apiClient.getEnrollmentSettings(TEST_SPACE_1); + expect(res.fleet_server.has_active).to.be(true); + }); + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/space_awareness/index.js b/x-pack/test/fleet_api_integration/apis/space_awareness/index.js index 4313c329104f2..3a3d9ea907150 100644 --- a/x-pack/test/fleet_api_integration/apis/space_awareness/index.js +++ b/x-pack/test/fleet_api_integration/apis/space_awareness/index.js @@ -11,5 +11,6 @@ export default function loadTests({ loadTestFile }) { loadTestFile(require.resolve('./uninstall_tokens')); loadTestFile(require.resolve('./agent_policies')); loadTestFile(require.resolve('./agents')); + loadTestFile(require.resolve('./enrollment_settings')); }); } From a455012d704f31efd81bfadca4d7333a53032582 Mon Sep 17 00:00:00 2001 From: Bharat Pasupula <123897612+bhapas@users.noreply.github.com> Date: Tue, 18 Jun 2024 21:53:17 +0200 Subject: [PATCH 079/127] [Security GenAI][Integration Assistant] Create OpenAPI spec for Integration Assistant APIs (#186085) --- .../build_integration.schema.yaml | 33 ++++ .../build_integration/build_integration.ts | 16 ++ .../categorization_route.schema.yaml | 43 +++++ .../categorization/categorization_route.ts | 30 ++++ .../check_pipeline/check_pipeline.schema.yaml | 34 ++++ .../api/check_pipeline/check_pipeline.ts | 21 +++ .../common/api/ecs/ecs_route.schema.yaml | 42 +++++ .../common/api/ecs/ecs_route.ts | 30 ++++ .../api/model/common_attributes.schema.yaml | 156 ++++++++++++++++ .../common/api/model/common_attributes.ts | 169 ++++++++++++++++++ .../model/processor_attributes.schema.yaml | 36 ++++ .../common/api/model/processor_attributes.ts | 52 ++++++ .../api/model/response_schemas.schema.yaml | 65 +++++++ .../common/api/model/response_schemas.ts | 49 +++++ .../api/related/related_route.schema.yaml | 43 +++++ .../common/api/related/related_route.ts | 30 ++++ .../integration_assistant/common/index.ts | 41 ++--- .../integration_assistant/common/types.ts | 119 ------------ .../server/graphs/ecs/graph.ts | 14 +- .../server/integration_builder/agent.ts | 6 +- .../integration_builder/build_integration.ts | 4 +- .../server/integration_builder/data_stream.ts | 4 +- .../server/integration_builder/pipeline.ts | 1 + .../server/routes/build_integration_routes.ts | 39 +--- .../server/routes/categorization_routes.ts | 84 ++++----- .../server/routes/ecs_routes.ts | 89 ++++----- .../server/routes/pipeline_routes.ts | 26 +-- .../server/routes/related_routes.ts | 80 ++++----- .../server/util/route_validation.ts | 21 +++ .../integration_assistant/tsconfig.json | 3 +- 30 files changed, 1028 insertions(+), 352 deletions(-) create mode 100644 x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/model/processor_attributes.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/model/processor_attributes.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/related/related_route.schema.yaml create mode 100644 x-pack/plugins/integration_assistant/common/api/related/related_route.ts delete mode 100644 x-pack/plugins/integration_assistant/common/types.ts create mode 100644 x-pack/plugins/integration_assistant/server/util/route_validation.ts diff --git a/x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.schema.yaml b/x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.schema.yaml new file mode 100644 index 0000000000000..798ead34114a6 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.schema.yaml @@ -0,0 +1,33 @@ +openapi: 3.0.3 +info: + title: Integration Assistatnt Build Integrarion API endpoint + version: "1" +paths: + /api/integration_assistant/build: + post: + summary: Builds Integration with the given input samples + operationId: BuildIntegration + x-codegen-enabled: false + description: Build Integration for the given input samples + tags: + - Build Integration API + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - integration + properties: + integration: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Integration" + responses: + 200: + description: Indicates a successful call. + content: + application/octet-stream: + schema: + # a binary file of any type + type: string + format: binary diff --git a/x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts b/x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts new file mode 100644 index 0000000000000..728b6d7403696 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +import { Integration } from '../model/common_attributes'; + +export type BuildIntegrationRequestBody = z.infer; +export const BuildIntegrationRequestBody = z.object({ + integration: Integration, +}); +export type BuildIntegrationRequestBodyInput = z.input; diff --git a/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.schema.yaml b/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.schema.yaml new file mode 100644 index 0000000000000..d46213e5c8afb --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.schema.yaml @@ -0,0 +1,43 @@ +openapi: 3.0.3 +info: + title: Integration Assistatnt Categorization API endpoint + version: "1" +paths: + /api/integration_assistant/categorization: + post: + summary: Builds Categorization processors based on the samples + operationId: Categorization + x-codegen-enabled: false + description: Perform Categorization for the given ecs mappings. + tags: + - Categorization API + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - packageName + - datastreamName + - rawSamples + - currentPipeline + - connectorId + properties: + packageName: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/PackageName" + datastreamName: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/DatastreamName" + rawSamples: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/RawSamples" + currentPipeline: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Pipeline" + connectorId: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Connector" + responses: + 200: + description: Indicates a successful call. + content: + application/json: + schema: + $ref: "../model/response_schemas.schema.yaml#/components/schemas/CategorizationAPIResponse" diff --git a/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts b/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts new file mode 100644 index 0000000000000..e3c81c95b7404 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +import { + Connector, + DatastreamName, + PackageName, + Pipeline, + RawSamples, +} from '../model/common_attributes'; +import { CategorizationAPIResponse } from '../model/response_schemas'; + +export type CategorizationRequestBody = z.infer; +export const CategorizationRequestBody = z.object({ + packageName: PackageName, + datastreamName: DatastreamName, + rawSamples: RawSamples, + currentPipeline: Pipeline, + connectorId: Connector, +}); +export type CategorizationRequestBodyInput = z.input; + +export type CategorizationResponse = z.infer; +export const CategorizationResponse = CategorizationAPIResponse; diff --git a/x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.schema.yaml b/x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.schema.yaml new file mode 100644 index 0000000000000..22785fc40bbf2 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.schema.yaml @@ -0,0 +1,34 @@ +openapi: 3.0.3 +info: + title: Integration Assistatnt Check Pipeline API endpoint + version: "1" +paths: + /api/integration_assistant/pipeline: + post: + summary: Checks if the pipeline is valid for the given samples + operationId: CheckPipeline + x-codegen-enabled: false + description: Check latest pipeline against the input samples. + tags: + - Check Pipeline API + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - rawSamples + - pipeline + properties: + rawSamples: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/RawSamples" + pipeline: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Pipeline" + responses: + 200: + description: Indicates a successful call. + content: + application/json: + schema: + $ref: "../model/response_schemas.schema.yaml#/components/schemas/CheckPipelineAPIResponse" diff --git a/x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts b/x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts new file mode 100644 index 0000000000000..39197c3675b21 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.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 { z } from 'zod'; + +import { Pipeline, RawSamples } from '../model/common_attributes'; +import { CheckPipelineAPIResponse } from '../model/response_schemas'; + +export type CheckPipelineRequestBody = z.infer; +export const CheckPipelineRequestBody = z.object({ + rawSamples: RawSamples, + pipeline: Pipeline, +}); +export type CheckPipelineRequestBodyInput = z.input; + +export type CheckPipelineResponse = z.infer; +export const CheckPipelineResponse = CheckPipelineAPIResponse; diff --git a/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.schema.yaml b/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.schema.yaml new file mode 100644 index 0000000000000..996635404e0b9 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.schema.yaml @@ -0,0 +1,42 @@ +openapi: 3.0.3 +info: + title: Integration Assistatnt ECS Mapping API endpoint + version: "1" +paths: + /api/integration_assistant/ecs: + post: + summary: Builds ECS Mapping based on the input samples + operationId: EcsMapping + x-codegen-enabled: false + description: Perform ECS mapping for the given input JSON samples + tags: + - ECS Mapping API + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - packageName + - datastreamName + - rawSamples + - connectorId + properties: + packageName: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/PackageName" + datastreamName: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/DatastreamName" + rawSamples: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/RawSamples" + mapping: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Mapping" + connectorId: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Connector" + responses: + 200: + description: Indicates a successful call. + content: + application/json: + schema: + $ref: "../model/response_schemas.schema.yaml#/components/schemas/EcsMappingAPIResponse" diff --git a/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts b/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts new file mode 100644 index 0000000000000..0a265c75da493 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +import { + Connector, + DatastreamName, + Mapping, + PackageName, + RawSamples, +} from '../model/common_attributes'; +import { EcsMappingAPIResponse } from '../model/response_schemas'; + +export type EcsMappingRequestBody = z.infer; +export const EcsMappingRequestBody = z.object({ + packageName: PackageName, + datastreamName: DatastreamName, + rawSamples: RawSamples, + mapping: Mapping.optional(), + connectorId: Connector, +}); +export type EcsMappingRequestBodyInput = z.input; + +export type EcsMappingResponse = z.infer; +export const EcsMappingResponse = EcsMappingAPIResponse; diff --git a/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml new file mode 100644 index 0000000000000..eb8c303edb5ab --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml @@ -0,0 +1,156 @@ +openapi: 3.0.3 +info: + title: Common Rule Attributes + version: "not applicable" +paths: {} +components: + x-codegen-enabled: false + schemas: + PackageName: + type: string + minLength: 1 + description: Package name for the integration to be built. + + DatastreamName: + type: string + minLength: 1 + description: Datastream name for the integration to be built. + + RawSamples: + type: array + items: + type: string + description: String array containing the json raw samples that are used for ecs mapping. + + Mapping: + type: object + description: mapping object to ECS Mapping Request. + + Connector: + type: string + description: LLM Connector to be used in each API request. + + Docs: + type: array + description: An array of processed documents. + items: + type: object + + Pipeline: + type: object + description: The pipeline object. + required: + - processors + properties: + name: + type: string + description: The name of the pipeline. + description: + type: string + description: The description of the pipeline. + version: + type: integer + description: The version of the pipeline. + processors: + type: array + items: + $ref: "../model/processor_attributes.schema.yaml#/components/schemas/ESProcessorItem" + description: The processors to execute. + on_failure: + type: array + items: + $ref: "../model/processor_attributes.schema.yaml#/components/schemas/ESProcessorItem" + description: The processors to execute if the pipeline fails. + + InputType: + type: string + description: The input type for the datastream to pull logs from. + enum: + - aws_cloudwatch + - aws_s3 + - azure_blob_storage + - azure_eventhub + - cloudfoundry + - filestream + - gcp_pubsub + - gcs + - http_endpoint + - journald + - kafka + - tcp + - udp + + Datastream: + type: object + description: The datastream object. + required: + - name + - title + - description + - inputTypes + - rawSamples + - pipeline + - docs + properties: + name: + type: string + description: The name of the datastream. + title: + type: string + description: The title of the datastream. + description: + type: string + description: The description of the datastream. + inputTypes: + type: array + items: + $ref: "#/components/schemas/InputType" + description: The input types of the datastream. + rawSamples: + $ref: "#/components/schemas/RawSamples" + description: The raw samples of the datastream. + pipeline: + $ref: "#/components/schemas/Pipeline" + description: The pipeline of the datastream. + docs: + $ref: "#/components/schemas/Docs" + description: The documents of the datastream. + + Integration: + type: object + description: The integration object. + required: + - name + - title + - description + - dataStreams + properties: + name: + type: string + description: The name of the integration. + title: + type: string + description: The title of the integration. + description: + type: string + description: The description of the integration. + dataStreams: + type: array + items: + $ref: "#/components/schemas/Datastream" + description: The datastreams of the integration. + logo: + type: string + description: The logo of the integration. + + PipelineResults: + type: array + description: An array of pipeline results. + items: + type: object + + Errors: + type: array + description: An array of errors. + items: + type: object diff --git a/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts new file mode 100644 index 0000000000000..426224a0622d0 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts @@ -0,0 +1,169 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +import { ESProcessorItem } from './processor_attributes'; + +/** + * Package name for the integration to be built. + */ +export type PackageName = z.infer; +export const PackageName = z.string().min(1); + +/** + * Datastream name for the integration to be built. + */ +export type DatastreamName = z.infer; +export const DatastreamName = z.string().min(1); + +/** + * String array containing the json raw samples that are used for ecs mapping. + */ +export type RawSamples = z.infer; +export const RawSamples = z.array(z.string()); + +/** + * mapping object to ECS Mapping Request. + */ +export type Mapping = z.infer; +export const Mapping = z.object({}); + +/** + * LLM Connector to be used in each API request. + */ +export type Connector = z.infer; +export const Connector = z.string(); + +/** + * An array of processed documents. + */ +export type Docs = z.infer; +export const Docs = z.array(z.object({})); + +/** + * The pipeline object. + */ +export type Pipeline = z.infer; +export const Pipeline = z.object({ + /** + * The name of the pipeline. + */ + name: z.string().optional(), + /** + * The description of the pipeline. + */ + description: z.string().optional(), + /** + * The version of the pipeline. + */ + version: z.number().int().optional(), + /** + * The processors to execute. + */ + processors: z.array(ESProcessorItem), + /** + * The processors to execute if the pipeline fails. + */ + on_failure: z.array(ESProcessorItem).optional(), +}); + +/** + * The input type for the datastream to pull logs from. + */ +export type InputType = z.infer; +export const InputType = z.enum([ + 'aws_cloudwatch', + 'aws_s3', + 'azure_blob_storage', + 'azure_eventhub', + 'cloudfoundry', + 'filestream', + 'gcp_pubsub', + 'gcs', + 'http_endpoint', + 'journald', + 'kafka', + 'tcp', + 'udp', +]); +export type InputTypeEnum = typeof InputType.enum; +export const InputTypeEnum = InputType.enum; + +/** + * The datastream object. + */ +export type Datastream = z.infer; +export const Datastream = z.object({ + /** + * The name of the datastream. + */ + name: z.string(), + /** + * The title of the datastream. + */ + title: z.string(), + /** + * The description of the datastream. + */ + description: z.string(), + /** + * The input types of the datastream. + */ + inputTypes: z.array(InputType), + /** + * The raw samples of the datastream. + */ + rawSamples: RawSamples, + /** + * The pipeline of the datastream. + */ + pipeline: Pipeline, + /** + * The documents of the datastream. + */ + docs: Docs, +}); + +/** + * The integration object. + */ +export type Integration = z.infer; +export const Integration = z.object({ + /** + * The name of the integration. + */ + name: z.string(), + /** + * The title of the integration. + */ + title: z.string(), + /** + * The description of the integration. + */ + description: z.string(), + /** + * The datastreams of the integration. + */ + dataStreams: z.array(Datastream), + /** + * The logo of the integration. + */ + logo: z.string().optional(), +}); + +/** + * An array of pipeline results. + */ +export type PipelineResults = z.infer; +export const PipelineResults = z.array(z.object({})); + +/** + * An array of errors. + */ +export type Errors = z.infer; +export const Errors = z.array(z.object({})); diff --git a/x-pack/plugins/integration_assistant/common/api/model/processor_attributes.schema.yaml b/x-pack/plugins/integration_assistant/common/api/model/processor_attributes.schema.yaml new file mode 100644 index 0000000000000..a0c930361737a --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/processor_attributes.schema.yaml @@ -0,0 +1,36 @@ +openapi: 3.0.3 +info: + title: Common Rule Attributes + version: "not applicable" +paths: {} +components: + x-codegen-enabled: false + schemas: + ESProcessorItem: + type: object + description: Processor item for the Elasticsearch processor. + additionalProperties: + $ref: "#/components/schemas/ESProcessorOptions" + + ESProcessorOptions: + type: object + description: Processor options for the Elasticsearch processor. + properties: + on_failure: + type: array + items: + $ref: "#/components/schemas/ESProcessorItem" + description: An array of items to execute if the processor fails. + ignore_failure: + type: boolean + description: If true, the processor continues to the next processor if the current processor fails. + ignore_missing: + type: boolean + description: If true, the processor continues to the next processor if the field is missing. + if: + type: string + description: Conditionally execute the processor. + tag: + type: string + description: A tag to assign to the document after processing. + additionalProperties: true diff --git a/x-pack/plugins/integration_assistant/common/api/model/processor_attributes.ts b/x-pack/plugins/integration_assistant/common/api/model/processor_attributes.ts new file mode 100644 index 0000000000000..a46f04e3fa130 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/processor_attributes.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/** + * Processor item for the Elasticsearch processor. + */ +export type ESProcessorItem = Record; +export const ESProcessorItem: z.ZodType = z + .object({}) + .catchall(z.lazy(() => ESProcessorOptions)); + +/** + * Processor options for the Elasticsearch processor. + */ +export interface ESProcessorOptions { + on_failure?: ESProcessorItem[]; + ignore_failure?: boolean; + ignore_missing?: boolean; + if?: string; + tag?: string; + [key: string]: unknown; +} +export const ESProcessorOptions = z + .object({ + /** + * An array of items to execute if the processor fails. + */ + on_failure: z.array(ESProcessorItem).optional(), + /** + * If true, the processor continues to the next processor if the current processor fails. + */ + ignore_failure: z.boolean().optional(), + /** + * If true, the processor continues to the next processor if the field is missing. + */ + ignore_missing: z.boolean().optional(), + /** + * Conditionally execute the processor. + */ + if: z.string().optional(), + /** + * A tag to assign to the document after processing. + */ + tag: z.string().optional(), + }) + .catchall(z.unknown()); diff --git a/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml new file mode 100644 index 0000000000000..100581cd21ceb --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml @@ -0,0 +1,65 @@ +openapi: 3.0.3 +info: + title: Response Schemas. + version: "not applicable" +paths: {} +components: + x-codegen-enabled: false + schemas: + EcsMappingAPIResponse: + type: object + required: + - results + properties: + results: + type: object + required: + - mapping + - pipeline + properties: + mapping: + $ref: "./common_attributes.schema.yaml#/components/schemas/Mapping" + pipeline: + $ref: "./common_attributes.schema.yaml#/components/schemas/Pipeline" + + CategorizationAPIResponse: + type: object + required: + - results + properties: + results: + type: object + required: + - docs + - pipeline + properties: + docs: + $ref: "./common_attributes.schema.yaml#/components/schemas/Docs" + pipeline: + $ref: "./common_attributes.schema.yaml#/components/schemas/Pipeline" + + RelatedAPIResponse: + type: object + required: + - results + properties: + results: + type: object + required: + - docs + - pipeline + properties: + docs: + $ref: "./common_attributes.schema.yaml#/components/schemas/Docs" + pipeline: + $ref: "./common_attributes.schema.yaml#/components/schemas/Pipeline" + + CheckPipelineAPIResponse: + type: object + required: + - pipelineResults + properties: + pipelineResults: + $ref: "./common_attributes.schema.yaml#/components/schemas/PipelineResults" + errors: + $ref: "./common_attributes.schema.yaml#/components/schemas/Errors" diff --git a/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts new file mode 100644 index 0000000000000..f8a42d2081488 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Response Schemas. + * version: not applicable + */ + +import { z } from 'zod'; + +import { Docs, Errors, Mapping, Pipeline, PipelineResults } from './common_attributes'; + +export type EcsMappingAPIResponse = z.infer; +export const EcsMappingAPIResponse = z.object({ + results: z.object({ + mapping: Mapping, + pipeline: Pipeline, + }), +}); + +export type CategorizationAPIResponse = z.infer; +export const CategorizationAPIResponse = z.object({ + results: z.object({ + docs: Docs, + pipeline: Pipeline, + }), +}); + +export type RelatedAPIResponse = z.infer; +export const RelatedAPIResponse = z.object({ + results: z.object({ + docs: Docs, + pipeline: Pipeline, + }), +}); + +export type CheckPipelineAPIResponse = z.infer; +export const CheckPipelineAPIResponse = z.object({ + pipelineResults: PipelineResults, + errors: Errors.optional(), +}); diff --git a/x-pack/plugins/integration_assistant/common/api/related/related_route.schema.yaml b/x-pack/plugins/integration_assistant/common/api/related/related_route.schema.yaml new file mode 100644 index 0000000000000..3172d9f9ba812 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/related/related_route.schema.yaml @@ -0,0 +1,43 @@ +openapi: 3.0.3 +info: + title: Integration Assistatnt Related API endpoint + version: "1" +paths: + /api/integration_assistant/related: + post: + summary: Builds related.* fields for integration with the given input samples + operationId: Related + x-codegen-enabled: false + description: Add Related mappings for the given samples. + tags: + - Related API + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - packageName + - datastreamName + - rawSamples + - currentPipeline + - connectorId + properties: + packageName: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/PackageName" + datastreamName: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/DatastreamName" + rawSamples: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/RawSamples" + currentPipeline: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Pipeline" + connectorId: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Connector" + responses: + 200: + description: Indicates a successful call. + content: + application/json: + schema: + $ref: "../model/response_schemas.schema.yaml#/components/schemas/RelatedAPIResponse" diff --git a/x-pack/plugins/integration_assistant/common/api/related/related_route.ts b/x-pack/plugins/integration_assistant/common/api/related/related_route.ts new file mode 100644 index 0000000000000..2b8c46866cc7b --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/related/related_route.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +import { + Connector, + DatastreamName, + PackageName, + Pipeline, + RawSamples, +} from '../model/common_attributes'; +import { RelatedAPIResponse } from '../model/response_schemas'; + +export type RelatedRequestBody = z.infer; +export const RelatedRequestBody = z.object({ + packageName: PackageName, + datastreamName: DatastreamName, + rawSamples: RawSamples, + currentPipeline: Pipeline, + connectorId: Connector, +}); +export type RelatedRequestBodyInput = z.input; + +export type RelatedResponse = z.infer; +export const RelatedResponse = RelatedAPIResponse; diff --git a/x-pack/plugins/integration_assistant/common/index.ts b/x-pack/plugins/integration_assistant/common/index.ts index 99b6cb8793a48..d5e72ede8e164 100644 --- a/x-pack/plugins/integration_assistant/common/index.ts +++ b/x-pack/plugins/integration_assistant/common/index.ts @@ -5,31 +5,28 @@ * 2.0. */ -export type { - BuildIntegrationApiRequest, - EcsMappingApiRequest, - CategorizationApiRequest, - RelatedApiRequest, - CategorizationApiResponse, - RelatedApiResponse, - EcsMappingApiResponse, - Pipeline, - ESProcessorItem, - ESProcessorOptions, - DataStream, - Integration, - InputTypes, - TestPipelineApiRequest, - TestPipelineApiResponse, -} from './types'; +export { BuildIntegrationRequestBody } from './api/build_integration/build_integration'; +export { + CategorizationRequestBody, + CategorizationResponse, +} from './api/categorization/categorization_route'; +export { + CheckPipelineRequestBody, + CheckPipelineResponse, +} from './api/check_pipeline/check_pipeline'; +export { EcsMappingRequestBody, EcsMappingResponse } from './api/ecs/ecs_route'; +export { RelatedRequestBody, RelatedResponse } from './api/related/related_route'; + +export type { Datastream, InputType, Integration, Pipeline } from './api/model/common_attributes'; +export type { ESProcessorItem } from './api/model/processor_attributes'; export { - PLUGIN_ID, - INTEGRATION_ASSISTANT_APP_ROUTE, - ECS_GRAPH_PATH, CATEGORIZATION_GRAPH_PATH, + ECS_GRAPH_PATH, + INTEGRATION_ASSISTANT_APP_ROUTE, + INTEGRATION_ASSISTANT_BASE_PATH, + INTEGRATION_BUILDER_PATH, + PLUGIN_ID, RELATED_GRAPH_PATH, TEST_PIPELINE_PATH, - INTEGRATION_BUILDER_PATH, - INTEGRATION_ASSISTANT_BASE_PATH, } from './constants'; diff --git a/x-pack/plugins/integration_assistant/common/types.ts b/x-pack/plugins/integration_assistant/common/types.ts deleted file mode 100644 index 50da197460e1e..0000000000000 --- a/x-pack/plugins/integration_assistant/common/types.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export interface ESProcessorOptions { - on_failure?: ESProcessorItem[]; - ignore_failure?: boolean; - ignore_missing?: boolean; - if?: string; - tag?: string; - [key: string]: unknown; -} - -export interface ESProcessorItem { - [processorName: string]: ESProcessorOptions; -} - -export interface Pipeline { - name?: string; - description?: string; - version?: number; - processors: ESProcessorItem[]; - on_failure?: ESProcessorItem[]; -} - -export enum InputTypes { - Cloudwatch = 'aws-cloudwatch', - S3 = 'aws-s3', - AzureBlobStorage = 'azure-blob-storage', - EventHub = 'azure-eventhub', - Cloudfoundry = 'cloudfoundry', - FileStream = 'filestream', - PubSub = 'gcp-pubsub', - GoogleCloudStorage = 'gcs', - HTTPListener = 'http_endpoint', - Journald = 'journald', - Kafka = 'kafka', - TCP = 'tcp', - UDP = 'udp', -} - -export interface DataStream { - name: string; - title: string; - description: string; - inputTypes: InputTypes[]; - rawSamples: string[]; - pipeline: object; - docs: object[]; -} - -export interface Integration { - name: string; - title: string; - description: string; - dataStreams: DataStream[]; - logo?: string; -} - -// Server Request Schemas -export interface BuildIntegrationApiRequest { - integration: Integration; -} - -export interface EcsMappingApiRequest { - packageName: string; - dataStreamName: string; - rawSamples: string[]; - mapping?: object; -} - -export interface CategorizationApiRequest { - packageName: string; - dataStreamName: string; - rawSamples: string[]; - currentPipeline: object; -} - -export interface RelatedApiRequest { - packageName: string; - dataStreamName: string; - rawSamples: string[]; - currentPipeline: object; -} - -export interface TestPipelineApiRequest { - rawSamples: string[]; - currentPipeline: Pipeline; -} - -// Server Response Schemas -export interface CategorizationApiResponse { - results: { - pipeline: object; - docs: object[]; - }; -} - -export interface RelatedApiResponse { - results: { - pipeline: object; - docs: object[]; - }; -} - -export interface EcsMappingApiResponse { - results: { - mapping: object; - pipeline: object; - }; -} - -export interface TestPipelineApiResponse { - pipelineResults: object[]; - errors?: object[]; -} diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts index 8c7347a8b5058..2c8e7283d4728 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts @@ -5,21 +5,21 @@ * 2.0. */ -import type { StateGraphArgs } from '@langchain/langgraph'; -import { StateGraph, END, START } from '@langchain/langgraph'; import type { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; +import type { StateGraphArgs } from '@langchain/langgraph'; +import { END, START, StateGraph } from '@langchain/langgraph'; +import type { EcsMappingState } from '../../types'; +import { mergeSamples, modifySamples } from '../../util/samples'; import { ECS_EXAMPLE_ANSWER, ECS_FIELDS } from './constants'; -import { modifySamples, mergeSamples } from '../../util/samples'; -import { createPipeline } from './pipeline'; -import { handleEcsMapping } from './mapping'; import { handleDuplicates } from './duplicates'; -import { handleMissingKeys } from './missing'; import { handleInvalidEcs } from './invalid'; +import { handleEcsMapping } from './mapping'; +import { handleMissingKeys } from './missing'; +import { createPipeline } from './pipeline'; import { handleValidateMappings } from './validate'; -import type { EcsMappingState } from '../../types'; const graphState: StateGraphArgs['channels'] = { ecs: { diff --git a/x-pack/plugins/integration_assistant/server/integration_builder/agent.ts b/x-pack/plugins/integration_assistant/server/integration_builder/agent.ts index 6d3282e00f18a..2f622eec103e5 100644 --- a/x-pack/plugins/integration_assistant/server/integration_builder/agent.ts +++ b/x-pack/plugins/integration_assistant/server/integration_builder/agent.ts @@ -6,10 +6,10 @@ */ import { join as joinPath } from 'path'; -import type { InputTypes } from '../../common'; -import { ensureDirSync, createSync, readSync } from '../util'; +import type { InputType } from '../../common'; +import { createSync, ensureDirSync, readSync } from '../util'; -export function createAgentInput(specificDataStreamDir: string, inputTypes: InputTypes[]): void { +export function createAgentInput(specificDataStreamDir: string, inputTypes: InputType[]): void { const agentDir = joinPath(specificDataStreamDir, 'agent', 'stream'); const agentTemplatesDir = joinPath(__dirname, '../templates/agent'); ensureDirSync(agentDir); diff --git a/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts b/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts index d2e29f769dd9a..05018d056b498 100644 --- a/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts +++ b/x-pack/plugins/integration_assistant/server/integration_builder/build_integration.ts @@ -9,7 +9,7 @@ import AdmZip from 'adm-zip'; import nunjucks from 'nunjucks'; import { tmpdir } from 'os'; import { join as joinPath } from 'path'; -import type { DataStream, Integration } from '../../common'; +import type { Datastream, Integration } from '../../common'; import { copySync, createSync, ensureDirSync, generateUniqueId } from '../util'; import { createAgentInput } from './agent'; import { createDatastream } from './data_stream'; @@ -113,7 +113,7 @@ async function createZipArchive(tmpPackageDir: string): Promise { function createPackageManifest(packageDir: string, integration: Integration): void { const uniqueInputs: { [key: string]: { type: string; title: string; description: string } } = {}; - integration.dataStreams.forEach((dataStream: DataStream) => { + integration.dataStreams.forEach((dataStream: Datastream) => { dataStream.inputTypes.forEach((inputType: string) => { if (!uniqueInputs[inputType]) { uniqueInputs[inputType] = { diff --git a/x-pack/plugins/integration_assistant/server/integration_builder/data_stream.ts b/x-pack/plugins/integration_assistant/server/integration_builder/data_stream.ts index fa9a24475e92e..8236666aec321 100644 --- a/x-pack/plugins/integration_assistant/server/integration_builder/data_stream.ts +++ b/x-pack/plugins/integration_assistant/server/integration_builder/data_stream.ts @@ -7,13 +7,13 @@ import nunjucks from 'nunjucks'; import { join as joinPath } from 'path'; -import type { DataStream } from '../../common'; +import type { Datastream } from '../../common'; import { copySync, createSync, ensureDirSync, listDirSync } from '../util'; export function createDatastream( packageName: string, specificDataStreamDir: string, - dataStream: DataStream + dataStream: Datastream ): void { const dataStreamName = dataStream.name; const pipelineDir = joinPath(specificDataStreamDir, 'elasticsearch', 'ingest_pipeline'); diff --git a/x-pack/plugins/integration_assistant/server/integration_builder/pipeline.ts b/x-pack/plugins/integration_assistant/server/integration_builder/pipeline.ts index 805535322b8e7..d733fd001be02 100644 --- a/x-pack/plugins/integration_assistant/server/integration_builder/pipeline.ts +++ b/x-pack/plugins/integration_assistant/server/integration_builder/pipeline.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { join as joinPath } from 'path'; import yaml from 'js-yaml'; import { createSync } from '../util'; diff --git a/x-pack/plugins/integration_assistant/server/routes/build_integration_routes.ts b/x-pack/plugins/integration_assistant/server/routes/build_integration_routes.ts index 191f189bacf8d..c3943c7d6398d 100644 --- a/x-pack/plugins/integration_assistant/server/routes/build_integration_routes.ts +++ b/x-pack/plugins/integration_assistant/server/routes/build_integration_routes.ts @@ -5,12 +5,11 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; import type { IRouter } from '@kbn/core/server'; -import type { BuildIntegrationApiRequest } from '../../common'; -import { INTEGRATION_BUILDER_PATH } from '../../common'; +import { BuildIntegrationRequestBody, INTEGRATION_BUILDER_PATH } from '../../common'; import { buildPackage } from '../integration_builder'; import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; +import { buildRouteValidationWithZod } from '../util/route_validation'; export function registerIntegrationBuilderRoutes( router: IRouter @@ -25,42 +24,12 @@ export function registerIntegrationBuilderRoutes( version: '1', validate: { request: { - body: schema.object({ - integration: schema.object({ - name: schema.string(), - title: schema.string(), - description: schema.string(), - logo: schema.maybe(schema.string()), - dataStreams: schema.arrayOf( - schema.object({ - name: schema.string(), - title: schema.string(), - description: schema.string(), - inputTypes: schema.arrayOf(schema.string()), - rawSamples: schema.arrayOf(schema.string()), - pipeline: schema.object({ - name: schema.maybe(schema.string()), - description: schema.maybe(schema.string()), - version: schema.maybe(schema.number()), - processors: schema.arrayOf( - schema.recordOf(schema.string(), schema.object({}, { unknowns: 'allow' })) - ), - on_failure: schema.maybe( - schema.arrayOf( - schema.recordOf(schema.string(), schema.object({}, { unknowns: 'allow' })) - ) - ), - }), - docs: schema.arrayOf(schema.object({}, { unknowns: 'allow' })), - }) - ), - }), - }), + body: buildRouteValidationWithZod(BuildIntegrationRequestBody), }, }, }, async (_, request, response) => { - const { integration } = request.body as BuildIntegrationApiRequest; + const { integration } = request.body; try { const zippedIntegration = await buildPackage(integration); return response.custom({ statusCode: 200, body: zippedIntegration }); diff --git a/x-pack/plugins/integration_assistant/server/routes/categorization_routes.ts b/x-pack/plugins/integration_assistant/server/routes/categorization_routes.ts index 4feb1c8b3bd8f..5ec9dc1b758ef 100644 --- a/x-pack/plugins/integration_assistant/server/routes/categorization_routes.ts +++ b/x-pack/plugins/integration_assistant/server/routes/categorization_routes.ts @@ -5,18 +5,21 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; -import type { IRouter } from '@kbn/core/server'; +import type { IKibanaResponse, IRouter } from '@kbn/core/server'; import { getRequestAbortedSignal } from '@kbn/data-plugin/server'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; -import type { CategorizationApiRequest, CategorizationApiResponse } from '../../common'; -import { CATEGORIZATION_GRAPH_PATH } from '../../common'; +import { + CATEGORIZATION_GRAPH_PATH, + CategorizationRequestBody, + CategorizationResponse, +} from '../../common'; import { ROUTE_HANDLER_TIMEOUT } from '../constants'; import { getCategorizationGraph } from '../graphs/categorization'; import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; +import { buildRouteValidationWithZod } from '../util/route_validation'; export function registerCategorizationRoutes( router: IRouter @@ -36,64 +39,53 @@ export function registerCategorizationRoutes( version: '1', validate: { request: { - body: schema.object({ - packageName: schema.string(), - dataStreamName: schema.string(), - rawSamples: schema.arrayOf(schema.string()), - currentPipeline: schema.any(), - connectorId: schema.maybe(schema.string()), - model: schema.maybe(schema.string()), - region: schema.maybe(schema.string()), - }), + body: buildRouteValidationWithZod(CategorizationRequestBody), }, }, }, - async (context, req, res) => { - const { packageName, dataStreamName, rawSamples, currentPipeline } = - req.body as CategorizationApiRequest; - + async (context, req, res): Promise> => { + const { packageName, datastreamName, rawSamples, currentPipeline } = req.body; const services = await context.resolve(['core']); const { client } = services.core.elasticsearch; const { getStartServices, logger } = await context.integrationAssistant; const [, { actions: actionsPlugin }] = await getStartServices(); - const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); - const connector = req.body.connectorId - ? await actionsClient.get({ id: req.body.connectorId }) - : (await actionsClient.getAll()).filter( - (connectorItem) => connectorItem.actionTypeId === '.bedrock' - )[0]; - const abortSignal = getRequestAbortedSignal(req.events.aborted$); - const isOpenAI = connector.actionTypeId === '.gen-ai'; - const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; + try { + const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); + const connector = req.body.connectorId + ? await actionsClient.get({ id: req.body.connectorId }) + : (await actionsClient.getAll()).filter( + (connectorItem) => connectorItem.actionTypeId === '.bedrock' + )[0]; + + const abortSignal = getRequestAbortedSignal(req.events.aborted$); + const isOpenAI = connector.actionTypeId === '.gen-ai'; + const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; - const model = new llmClass({ - actions: actionsPlugin, - connectorId: connector.id, - request: req, - logger, - llmType: isOpenAI ? 'openai' : 'bedrock', - model: req.body.model || connector.config?.defaultModel, - temperature: 0.05, - maxTokens: 4096, - signal: abortSignal, - streaming: false, - }); + const model = new llmClass({ + actions: actionsPlugin, + connectorId: connector.id, + request: req, + logger, + llmType: isOpenAI ? 'openai' : 'bedrock', + model: connector.config?.defaultModel, + temperature: 0.05, + maxTokens: 4096, + signal: abortSignal, + streaming: false, + }); - const graph = await getCategorizationGraph(client, model); - let results = { results: { docs: {}, pipeline: {} } }; - try { - results = (await graph.invoke({ + const graph = await getCategorizationGraph(client, model); + const results = await graph.invoke({ packageName, - dataStreamName, + datastreamName, rawSamples, currentPipeline, - })) as CategorizationApiResponse; + }); + return res.ok({ body: CategorizationResponse.parse(results) }); } catch (e) { return res.badRequest({ body: e }); } - - return res.ok({ body: results }); } ); } diff --git a/x-pack/plugins/integration_assistant/server/routes/ecs_routes.ts b/x-pack/plugins/integration_assistant/server/routes/ecs_routes.ts index d62e31389af46..1ee7659b3598b 100644 --- a/x-pack/plugins/integration_assistant/server/routes/ecs_routes.ts +++ b/x-pack/plugins/integration_assistant/server/routes/ecs_routes.ts @@ -5,18 +5,17 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; -import type { IRouter } from '@kbn/core/server'; +import type { IKibanaResponse, IRouter } from '@kbn/core/server'; import { getRequestAbortedSignal } from '@kbn/data-plugin/server'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; -import { ECS_GRAPH_PATH } from '../../common'; -import type { EcsMappingApiRequest, EcsMappingApiResponse } from '../../common/types'; +import { ECS_GRAPH_PATH, EcsMappingRequestBody, EcsMappingResponse } from '../../common'; import { ROUTE_HANDLER_TIMEOUT } from '../constants'; import { getEcsGraph } from '../graphs/ecs'; import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; +import { buildRouteValidationWithZod } from '../util/route_validation'; export function registerEcsRoutes(router: IRouter) { router.versioned @@ -34,70 +33,60 @@ export function registerEcsRoutes(router: IRouter { - const { packageName, dataStreamName, rawSamples, mapping } = - req.body as EcsMappingApiRequest; - + async (context, req, res): Promise> => { + const { packageName, datastreamName, rawSamples, mapping } = req.body; const { getStartServices, logger } = await context.integrationAssistant; const [, { actions: actionsPlugin }] = await getStartServices(); - const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); - const connector = req.body.connectorId - ? await actionsClient.get({ id: req.body.connectorId }) - : (await actionsClient.getAll()).filter( - (connectorItem) => connectorItem.actionTypeId === '.bedrock' - )[0]; - const abortSignal = getRequestAbortedSignal(req.events.aborted$); - const isOpenAI = connector.actionTypeId === '.gen-ai'; - const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; + try { + const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); + const connector = req.body.connectorId + ? await actionsClient.get({ id: req.body.connectorId }) + : (await actionsClient.getAll()).filter( + (connectorItem) => connectorItem.actionTypeId === '.bedrock' + )[0]; - const model = new llmClass({ - actions: actionsPlugin, - connectorId: connector.id, - request: req, - logger, - llmType: isOpenAI ? 'openai' : 'bedrock', - model: req.body.model || connector.config?.defaultModel, - temperature: 0.05, - maxTokens: 4096, - signal: abortSignal, - streaming: false, - }); + const abortSignal = getRequestAbortedSignal(req.events.aborted$); + const isOpenAI = connector.actionTypeId === '.gen-ai'; + const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; - const graph = await getEcsGraph(model); - let results = { results: { mapping: {}, pipeline: {} } }; - try { + const model = new llmClass({ + actions: actionsPlugin, + connectorId: connector.id, + request: req, + logger, + llmType: isOpenAI ? 'openai' : 'bedrock', + model: connector.config?.defaultModel, + temperature: 0.05, + maxTokens: 4096, + signal: abortSignal, + streaming: false, + }); + + const graph = await getEcsGraph(model); + + let results; if (req.body?.mapping) { - results = (await graph.invoke({ + results = await graph.invoke({ packageName, - dataStreamName, + datastreamName, rawSamples, mapping, - })) as EcsMappingApiResponse; + }); } else - results = (await graph.invoke({ + results = await graph.invoke({ packageName, - dataStreamName, + datastreamName, rawSamples, - })) as EcsMappingApiResponse; + }); + return res.ok({ body: EcsMappingResponse.parse(results) }); } catch (e) { return res.badRequest({ body: e }); } - - return res.ok({ body: results }); } ); } diff --git a/x-pack/plugins/integration_assistant/server/routes/pipeline_routes.ts b/x-pack/plugins/integration_assistant/server/routes/pipeline_routes.ts index 17e4f667a6df5..4b4ccc0a859a5 100644 --- a/x-pack/plugins/integration_assistant/server/routes/pipeline_routes.ts +++ b/x-pack/plugins/integration_assistant/server/routes/pipeline_routes.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; -import type { IRouter } from '@kbn/core/server'; -import { TEST_PIPELINE_PATH } from '../../common'; -import type { TestPipelineApiRequest, TestPipelineApiResponse } from '../../common/types'; +import type { IKibanaResponse, IRouter } from '@kbn/core/server'; +import { CheckPipelineRequestBody, CheckPipelineResponse, TEST_PIPELINE_PATH } from '../../common'; import { ROUTE_HANDLER_TIMEOUT } from '../constants'; import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; import { testPipeline } from '../util/pipeline'; +import { buildRouteValidationWithZod } from '../util/route_validation'; export function registerPipelineRoutes(router: IRouter) { router.versioned @@ -29,32 +28,23 @@ export function registerPipelineRoutes(router: IRouter { - const { rawSamples, currentPipeline } = req.body as TestPipelineApiRequest; + async (context, req, res): Promise> => { + const { rawSamples, pipeline } = req.body; const services = await context.resolve(['core']); const { client } = services.core.elasticsearch; - let results: TestPipelineApiResponse = { pipelineResults: [], errors: [] }; try { - results = (await testPipeline( - rawSamples, - currentPipeline, - client - )) as TestPipelineApiResponse; + const results = await testPipeline(rawSamples, pipeline, client); if (results?.errors && results.errors.length > 0) { return res.badRequest({ body: JSON.stringify(results.errors) }); } + return res.ok({ body: CheckPipelineResponse.parse(results) }); } catch (e) { return res.badRequest({ body: e }); } - - return res.ok({ body: results }); } ); } diff --git a/x-pack/plugins/integration_assistant/server/routes/related_routes.ts b/x-pack/plugins/integration_assistant/server/routes/related_routes.ts index 934b9711027ee..90533742e8ff7 100644 --- a/x-pack/plugins/integration_assistant/server/routes/related_routes.ts +++ b/x-pack/plugins/integration_assistant/server/routes/related_routes.ts @@ -5,18 +5,17 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; -import type { IRouter } from '@kbn/core/server'; +import type { IKibanaResponse, IRouter } from '@kbn/core/server'; import { getRequestAbortedSignal } from '@kbn/data-plugin/server'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; -import { RELATED_GRAPH_PATH } from '../../common'; -import type { RelatedApiRequest, RelatedApiResponse } from '../../common/types'; +import { RELATED_GRAPH_PATH, RelatedRequestBody, RelatedResponse } from '../../common'; import { ROUTE_HANDLER_TIMEOUT } from '../constants'; import { getRelatedGraph } from '../graphs/related'; import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; +import { buildRouteValidationWithZod } from '../util/route_validation'; export function registerRelatedRoutes(router: IRouter) { router.versioned @@ -34,65 +33,52 @@ export function registerRelatedRoutes(router: IRouter { - const { packageName, dataStreamName, rawSamples, currentPipeline } = - req.body as RelatedApiRequest; - + async (context, req, res): Promise> => { + const { packageName, datastreamName, rawSamples, currentPipeline } = req.body; const services = await context.resolve(['core']); const { client } = services.core.elasticsearch; const { getStartServices, logger } = await context.integrationAssistant; const [, { actions: actionsPlugin }] = await getStartServices(); - const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); - const connector = req.body.connectorId - ? await actionsClient.get({ id: req.body.connectorId }) - : (await actionsClient.getAll()).filter( - (connectorItem) => connectorItem.actionTypeId === '.bedrock' - )[0]; + try { + const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); + const connector = req.body.connectorId + ? await actionsClient.get({ id: req.body.connectorId }) + : (await actionsClient.getAll()).filter( + (connectorItem) => connectorItem.actionTypeId === '.bedrock' + )[0]; - const isOpenAI = connector.actionTypeId === '.gen-ai'; - const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; - const abortSignal = getRequestAbortedSignal(req.events.aborted$); + const isOpenAI = connector.actionTypeId === '.gen-ai'; + const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; + const abortSignal = getRequestAbortedSignal(req.events.aborted$); - const model = new llmClass({ - actions: actionsPlugin, - connectorId: connector.id, - request: req, - logger, - llmType: isOpenAI ? 'openai' : 'bedrock', - model: req.body.model || connector.config?.defaultModel, - temperature: 0.05, - maxTokens: 4096, - signal: abortSignal, - streaming: false, - }); + const model = new llmClass({ + actions: actionsPlugin, + connectorId: connector.id, + request: req, + logger, + llmType: isOpenAI ? 'openai' : 'bedrock', + model: connector.config?.defaultModel, + temperature: 0.05, + maxTokens: 4096, + signal: abortSignal, + streaming: false, + }); - const graph = await getRelatedGraph(client, model); - let results = { results: { docs: {}, pipeline: {} } }; - try { - results = (await graph.invoke({ + const graph = await getRelatedGraph(client, model); + const results = await graph.invoke({ packageName, - dataStreamName, + datastreamName, rawSamples, currentPipeline, - })) as RelatedApiResponse; + }); + return res.ok({ body: RelatedResponse.parse(results) }); } catch (e) { return res.badRequest({ body: e }); } - - return res.ok({ body: results }); } ); } diff --git a/x-pack/plugins/integration_assistant/server/util/route_validation.ts b/x-pack/plugins/integration_assistant/server/util/route_validation.ts new file mode 100644 index 0000000000000..e9f9c08b74c81 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/util/route_validation.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 type { RouteValidationFunction, RouteValidationResultFactory } from '@kbn/core/server'; +import { stringifyZodError } from '@kbn/zod-helpers'; +import type { TypeOf, ZodType } from 'zod'; + +export const buildRouteValidationWithZod = + >(schema: T): RouteValidationFunction => + (inputValue: unknown, validationResult: RouteValidationResultFactory) => { + const decoded = schema.safeParse(inputValue); + if (decoded.success) { + return validationResult.ok(decoded.data); + } else { + return validationResult.badRequest(stringifyZodError(decoded.error)); + } + }; diff --git a/x-pack/plugins/integration_assistant/tsconfig.json b/x-pack/plugins/integration_assistant/tsconfig.json index 67a763a73f7f3..515611f12f166 100644 --- a/x-pack/plugins/integration_assistant/tsconfig.json +++ b/x-pack/plugins/integration_assistant/tsconfig.json @@ -17,6 +17,7 @@ "@kbn/langchain", "@kbn/core-elasticsearch-server", "@kbn/actions-plugin", - "@kbn/data-plugin" + "@kbn/data-plugin", + "@kbn/zod-helpers" ] } From 7a0065d5b67805c82695f4cce0998a89f77a4ae7 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Tue, 18 Jun 2024 22:22:19 +0200 Subject: [PATCH 080/127] [Security Solution] Add missing Lists API OpenAPI specifications (#185865) **Resolves:** https://github.com/elastic/kibana/issues/183821 ## Summary This PR adds missing OpenAPI specifications for Lists API which are the following - `POST /api/lists` - `GET /api/lists` - `PUT /api/lists` - `DELETE /api/lists` - `PATCH /api/lists` - `GET /api/lists/_find` - `GET /api/lists/privileges` - `POST /api/lists/items` - `GET /api/lists/items` - `PUT /api/lists/items` - `DELETE /api/lists/items` - `PATCH /api/lists/items` - `POST /api/lists/items/_export` - `POST /api/lists/items/_import` - `GET /api/lists/items/_find` - `POST /api/lists/index` - `GET /api/lists/index` - `DELETE /api/lists/index` **Note:** Code generation is enabled for the added specs to verify that it works and produces expected results. Generated Zod schemas and types aren't integrated in the route's code. --- .../security_solution_codegen.sh | 12 ++ .github/CODEOWNERS | 2 + package.json | 2 + packages/kbn-openapi-common/README.md | 3 + packages/kbn-openapi-common/kibana.jsonc | 5 + packages/kbn-openapi-common/package.json | 11 ++ .../schemas/error_responses.gen.ts | 31 +++++ .../schemas/error_responses.schema.yaml | 32 +++++ .../schemas/primitives.gen.ts | 33 +++++ .../schemas/primitives.schema.yaml | 18 +++ .../scripts/openapi_generate.js | 22 +++ packages/kbn-openapi-common/tsconfig.json | 10 ++ .../README.md | 20 +++ .../api/create_list/create_list.gen.ts | 43 ++++++ .../api/create_list/create_list.schema.yaml | 82 ++++++++++++ .../create_list_index.gen.ts | 23 ++++ .../create_list_index.schema.yaml | 56 ++++++++ .../create_list_item/create_list_item.gen.ts | 37 ++++++ .../create_list_item.schema.yaml | 78 +++++++++++ .../api/delete_list/delete_list.gen.ts | 36 +++++ .../api/delete_list/delete_list.schema.yaml | 71 ++++++++++ .../delete_list_index.gen.ts | 23 ++++ .../delete_list_index.schema.yaml | 56 ++++++++ .../delete_list_item/delete_list_item.gen.ts | 45 +++++++ .../delete_list_item.schema.yaml | 83 ++++++++++++ .../export_list_item/export_list_item.gen.ts | 29 ++++ .../export_list_item.schema.yaml | 61 +++++++++ .../api/find_list/find_list.gen.ts | 70 ++++++++++ .../api/find_list/find_list.schema.yaml | 119 +++++++++++++++++ .../api/find_list_item/find_list_item.gen.ts | 75 +++++++++++ .../find_list_item/find_list_item.schema.yaml | 125 ++++++++++++++++++ .../get_list_privileges.gen.ts | 43 ++++++ .../get_list_privileges.schema.yaml | 115 ++++++++++++++++ .../import_list_item/import_list_item.gen.ts | 49 +++++++ .../import_list_item.schema.yaml | 102 ++++++++++++++ .../api/index.ts | 26 ++++ .../api/model/list_common.gen.ts | 73 ++++++++++ .../api/model/list_common.schema.yaml | 59 +++++++++ .../api/model/list_schemas.gen.ts | 67 ++++++++++ .../api/model/list_schemas.schema.yaml | 103 +++++++++++++++ .../api/patch_list/patch_list.gen.ts | 35 +++++ .../api/patch_list/patch_list.schema.yaml | 75 +++++++++++ .../patch_list_item/patch_list_item.gen.ts | 37 ++++++ .../patch_list_item.schema.yaml | 77 +++++++++++ .../api/read_list/read_list.gen.ts | 33 +++++ .../api/read_list/read_list.schema.yaml | 59 +++++++++ .../read_list_index/read_list_index.gen.ts | 24 ++++ .../read_list_index.schema.yaml | 58 ++++++++ .../api/read_list_item/read_list_item.gen.ts | 41 ++++++ .../read_list_item/read_list_item.schema.yaml | 75 +++++++++++ .../api/update_list/update_list.gen.ts | 35 +++++ .../api/update_list/update_list.schema.yaml | 77 +++++++++++ .../update_list_item/update_list_item.gen.ts | 33 +++++ .../update_list_item.schema.yaml | 71 ++++++++++ .../kibana.jsonc | 5 + .../package.json | 10 ++ .../scripts/openapi_generate.js | 22 +++ .../tsconfig.json | 10 ++ packages/kbn-zod-helpers/index.ts | 1 + .../src/build_route_validation_with_zod.ts | 48 +++++++ packages/kbn-zod-helpers/tsconfig.json | 4 +- tsconfig.base.json | 4 + x-pack/plugins/lists/common/api/index.ts | 16 --- .../values/create_list/create_list_route.ts | 15 --- .../create_list_index_route.ts | 10 -- .../create_list_item_route.ts | 10 -- .../values/delete_list/delete_list_route.ts | 10 -- .../delete_list_index_route.ts | 10 -- .../delete_list_item_route.ts | 18 --- .../api/values/find_list/find_list_route.ts | 10 -- .../find_list_item/find_list_item_route.ts | 18 --- .../import_list_item_route.ts | 13 -- .../api/values/patch_list/patch_list_route.ts | 10 -- .../patch_list_item/patch_list_item_route.ts | 10 -- .../api/values/read_list/read_list_route.ts | 10 -- .../read_list_index/read_list_index_route.ts | 10 -- .../read_list_item/read_list_item_route.ts | 18 --- .../values/update_list/update_list_route.ts | 10 -- .../update_list_item_route.ts | 10 -- .../request/create_list_schema.mock.ts | 8 +- .../request/update_list_schema.mock.ts | 6 +- .../server/routes/list/create_list_route.ts | 22 +-- .../server/routes/list/delete_list_route.ts | 23 ++-- .../routes/list/import_list_item_route.ts | 26 ++-- .../server/routes/list/patch_list_route.ts | 15 +-- .../server/routes/list/read_list_route.ts | 15 +-- .../server/routes/list/update_list_route.ts | 15 +-- .../list_index/create_list_index_route.ts | 10 +- .../list_index/delete_list_index_route.ts | 10 +- .../list_index/export_list_item_route.ts | 7 +- .../routes/list_index/find_list_route.ts | 16 +-- .../list_index/read_list_index_route.ts | 18 +-- .../list_item/create_list_item_route.ts | 19 ++- .../list_item/delete_list_item_route.ts | 29 ++-- .../routes/list_item/find_list_item_route.ts | 25 ++-- .../routes/list_item/patch_list_item_route.ts | 18 ++- .../routes/list_item/read_list_item_route.ts | 29 ++-- .../list_item/update_list_item_route.ts | 18 ++- x-pack/plugins/lists/tsconfig.json | 11 +- .../signals/create_signals_migration_route.ts | 2 +- .../signals/delete_signals_migration_route.ts | 2 +- .../finalize_signals_migration_route.ts | 2 +- .../get_signals_migration_status_route.ts | 2 +- .../signals/open_close_signals_route.ts | 2 +- .../routes/signals/query_signals_route.ts | 2 +- .../signals/set_alert_assignees_route.ts | 2 +- .../routes/signals/set_alert_tags_route.ts | 2 +- .../users/suggest_user_profiles_route.ts | 2 +- .../api/rules/bulk_actions/route.ts | 2 +- .../api/rules/bulk_create_rules/route.ts | 2 +- .../api/rules/bulk_delete_rules/route.ts | 2 +- .../api/rules/bulk_patch_rules/route.ts | 3 +- .../api/rules/bulk_update_rules/route.ts | 4 +- .../api/rules/create_rule/route.ts | 2 +- .../api/rules/delete_rule/route.ts | 2 +- .../api/rules/export_rules/route.ts | 4 +- .../api/rules/find_rules/route.ts | 3 +- .../api/rules/import_rules/route.ts | 2 +- .../api/rules/patch_rule/route.ts | 2 +- .../api/rules/read_rule/route.ts | 2 +- .../api/rules/update_rule/route.ts | 2 +- .../get_rule_execution_events_route.ts | 2 +- .../get_rule_execution_results_route.ts | 2 +- .../rule_preview/api/preview_rules/route.ts | 3 +- .../asset_criticality/routes/delete.ts | 2 +- .../asset_criticality/routes/get.ts | 2 +- .../asset_criticality/routes/upsert.ts | 2 +- .../risk_score/routes/calculation.ts | 2 +- .../risk_score/routes/entity_calculation.ts | 5 +- .../risk_score/routes/preview.ts | 3 +- .../build_validation/route_validation.ts | 13 -- .../items/find_list_items.ts | 49 +++---- yarn.lock | 8 ++ 133 files changed, 2964 insertions(+), 511 deletions(-) create mode 100644 packages/kbn-openapi-common/README.md create mode 100644 packages/kbn-openapi-common/kibana.jsonc create mode 100644 packages/kbn-openapi-common/package.json create mode 100644 packages/kbn-openapi-common/schemas/error_responses.gen.ts create mode 100644 packages/kbn-openapi-common/schemas/error_responses.schema.yaml create mode 100644 packages/kbn-openapi-common/schemas/primitives.gen.ts create mode 100644 packages/kbn-openapi-common/schemas/primitives.schema.yaml create mode 100644 packages/kbn-openapi-common/scripts/openapi_generate.js create mode 100644 packages/kbn-openapi-common/tsconfig.json create mode 100644 packages/kbn-securitysolution-lists-common/README.md create mode 100644 packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/find_list/find_list.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/find_list/find_list.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/index.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts create mode 100644 packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml create mode 100644 packages/kbn-securitysolution-lists-common/kibana.jsonc create mode 100644 packages/kbn-securitysolution-lists-common/package.json create mode 100644 packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js create mode 100644 packages/kbn-securitysolution-lists-common/tsconfig.json create mode 100644 packages/kbn-zod-helpers/src/build_route_validation_with_zod.ts delete mode 100644 x-pack/plugins/lists/common/api/values/create_list/create_list_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/create_list_index/create_list_index_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/create_list_item/create_list_item_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/delete_list/delete_list_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/delete_list_index/delete_list_index_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/delete_list_item/delete_list_item_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/find_list/find_list_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/find_list_item/find_list_item_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/import_list_item/import_list_item_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/patch_list/patch_list_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/patch_list_item/patch_list_item_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/read_list/read_list_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/read_list_index/read_list_index_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/read_list_item/read_list_item_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/update_list/update_list_route.ts delete mode 100644 x-pack/plugins/lists/common/api/values/update_list_item/update_list_item_route.ts diff --git a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh index b36a9e52001e4..5a37c8a08d99a 100755 --- a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh +++ b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh @@ -6,5 +6,17 @@ source .buildkite/scripts/common/util.sh echo --- Security Solution OpenAPI Code Generation +echo OpenAPI Common Package + +(cd packages/kbn-openapi-common && yarn openapi:generate) +check_for_changed_files "yarn openapi:generate" true + +echo Lists API Common Package + +(cd packages/kbn-securitysolution-lists-common && yarn openapi:generate) +check_for_changed_files "yarn openapi:generate" true + +echo Security Solution Plugin + (cd x-pack/plugins/security_solution && yarn openapi:generate) check_for_changed_files "yarn openapi:generate" true \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e519143df765d..690698e02a142 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -622,6 +622,7 @@ x-pack/plugins/observability_solution/observability_shared @elastic/observabilit x-pack/test/security_api_integration/plugins/oidc_provider @elastic/kibana-security test/common/plugins/otel_metrics @elastic/obs-ux-infra_services-team packages/kbn-openapi-bundler @elastic/security-detection-rule-management +packages/kbn-openapi-common @elastic/security-detection-rule-management packages/kbn-openapi-generator @elastic/security-detection-rule-management packages/kbn-optimizer @elastic/kibana-operations packages/kbn-optimizer-webpack-helpers @elastic/kibana-operations @@ -752,6 +753,7 @@ packages/kbn-securitysolution-list-api @elastic/security-detection-engine packages/kbn-securitysolution-list-constants @elastic/security-detection-engine packages/kbn-securitysolution-list-hooks @elastic/security-detection-engine packages/kbn-securitysolution-list-utils @elastic/security-detection-engine +packages/kbn-securitysolution-lists-common @elastic/security-detection-engine packages/kbn-securitysolution-rules @elastic/security-detection-engine packages/kbn-securitysolution-t-grid @elastic/security-detection-engine packages/kbn-securitysolution-utils @elastic/security-detection-engine diff --git a/package.json b/package.json index 338db19ea67a1..48abd4ddd30b7 100644 --- a/package.json +++ b/package.json @@ -647,6 +647,7 @@ "@kbn/observability-shared-plugin": "link:x-pack/plugins/observability_solution/observability_shared", "@kbn/oidc-provider-plugin": "link:x-pack/test/security_api_integration/plugins/oidc_provider", "@kbn/open-telemetry-instrumented-plugin": "link:test/common/plugins/otel_metrics", + "@kbn/openapi-common": "link:packages/kbn-openapi-common", "@kbn/osquery-io-ts-types": "link:packages/kbn-osquery-io-ts-types", "@kbn/osquery-plugin": "link:x-pack/plugins/osquery", "@kbn/paertial-results-example-plugin": "link:examples/partial_results_example", @@ -762,6 +763,7 @@ "@kbn/securitysolution-list-constants": "link:packages/kbn-securitysolution-list-constants", "@kbn/securitysolution-list-hooks": "link:packages/kbn-securitysolution-list-hooks", "@kbn/securitysolution-list-utils": "link:packages/kbn-securitysolution-list-utils", + "@kbn/securitysolution-lists-common": "link:packages/kbn-securitysolution-lists-common", "@kbn/securitysolution-rules": "link:packages/kbn-securitysolution-rules", "@kbn/securitysolution-t-grid": "link:packages/kbn-securitysolution-t-grid", "@kbn/securitysolution-utils": "link:packages/kbn-securitysolution-utils", diff --git a/packages/kbn-openapi-common/README.md b/packages/kbn-openapi-common/README.md new file mode 100644 index 0000000000000..7199904b486be --- /dev/null +++ b/packages/kbn-openapi-common/README.md @@ -0,0 +1,3 @@ +# OpenAPI Common Schemas + +This package contains common reusable schemas like `NonEmptyString` to be reused by any OpenAPI specification defined inside Kibana. diff --git a/packages/kbn-openapi-common/kibana.jsonc b/packages/kbn-openapi-common/kibana.jsonc new file mode 100644 index 0000000000000..4254feb1b8a73 --- /dev/null +++ b/packages/kbn-openapi-common/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/openapi-common", + "owner": "@elastic/security-detection-rule-management" +} diff --git a/packages/kbn-openapi-common/package.json b/packages/kbn-openapi-common/package.json new file mode 100644 index 0000000000000..c90099eacadf0 --- /dev/null +++ b/packages/kbn-openapi-common/package.json @@ -0,0 +1,11 @@ +{ + "description": "OpenAPI common schemas for Kibana", + "license": "SSPL-1.0 OR Elastic License 2.0", + "name": "@kbn/openapi-common", + "private": true, + "version": "1.0.0", + "scripts": { + "openapi:generate": "node scripts/openapi_generate" + } +} + diff --git a/packages/kbn-openapi-common/schemas/error_responses.gen.ts b/packages/kbn-openapi-common/schemas/error_responses.gen.ts new file mode 100644 index 0000000000000..1555dcbb612e1 --- /dev/null +++ b/packages/kbn-openapi-common/schemas/error_responses.gen.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Error response schemas + * version: not applicable + */ + +import { z } from 'zod'; + +export type PlatformErrorResponse = z.infer; +export const PlatformErrorResponse = z.object({ + statusCode: z.number().int(), + error: z.string(), + message: z.string(), +}); + +export type SiemErrorResponse = z.infer; +export const SiemErrorResponse = z.object({ + status_code: z.number().int(), + message: z.string(), +}); diff --git a/packages/kbn-openapi-common/schemas/error_responses.schema.yaml b/packages/kbn-openapi-common/schemas/error_responses.schema.yaml new file mode 100644 index 0000000000000..9574103b9411e --- /dev/null +++ b/packages/kbn-openapi-common/schemas/error_responses.schema.yaml @@ -0,0 +1,32 @@ +openapi: 3.0.0 +info: + title: Error response schemas + version: 'not applicable' +paths: {} +components: + x-codegen-enabled: true + schemas: + PlatformErrorResponse: + type: object + properties: + statusCode: + type: integer + error: + type: string + message: + type: string + required: + - statusCode + - error + - message + + SiemErrorResponse: + type: object + properties: + status_code: + type: integer + message: + type: string + required: + - status_code + - message diff --git a/packages/kbn-openapi-common/schemas/primitives.gen.ts b/packages/kbn-openapi-common/schemas/primitives.gen.ts new file mode 100644 index 0000000000000..a9027448d7e77 --- /dev/null +++ b/packages/kbn-openapi-common/schemas/primitives.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Shared Primitives Schema + * version: not applicable + */ + +import { z } from 'zod'; + +/** + * A string that is not empty and does not contain only whitespace + */ +export type NonEmptyString = z.infer; +export const NonEmptyString = z + .string() + .min(1) + .regex(/^(?! *$).+$/); + +/** + * A universally unique identifier + */ +export type UUID = z.infer; +export const UUID = z.string().uuid(); diff --git a/packages/kbn-openapi-common/schemas/primitives.schema.yaml b/packages/kbn-openapi-common/schemas/primitives.schema.yaml new file mode 100644 index 0000000000000..177ad2ed30ecc --- /dev/null +++ b/packages/kbn-openapi-common/schemas/primitives.schema.yaml @@ -0,0 +1,18 @@ +openapi: 3.0.0 +info: + title: Shared Primitives Schema + version: 'not applicable' +paths: {} +components: + x-codegen-enabled: true + schemas: + NonEmptyString: + type: string + pattern: ^(?! *$).+$ + minLength: 1 + description: A string that is not empty and does not contain only whitespace + + UUID: + type: string + format: uuid + description: A universally unique identifier diff --git a/packages/kbn-openapi-common/scripts/openapi_generate.js b/packages/kbn-openapi-common/scripts/openapi_generate.js new file mode 100644 index 0000000000000..e8e7ffca22ede --- /dev/null +++ b/packages/kbn-openapi-common/scripts/openapi_generate.js @@ -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 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. + */ + +require('../../../src/setup_node_env'); +const { resolve } = require('path'); +const { generate } = require('@kbn/openapi-generator'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await generate({ + title: 'OpenAPI Common Schemas (kbn-openapi-common)', + rootDir: ROOT, + sourceGlob: './schemas/**/*.schema.yaml', + templateName: 'zod_operation_schema', + }); +})(); diff --git a/packages/kbn-openapi-common/tsconfig.json b/packages/kbn-openapi-common/tsconfig.json new file mode 100644 index 0000000000000..168274f98f058 --- /dev/null +++ b/packages/kbn-openapi-common/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "exclude": ["target/**/*"], + "extends": "../../tsconfig.base.json", + "include": ["**/*.ts"], + "kbn_references": [] +} diff --git a/packages/kbn-securitysolution-lists-common/README.md b/packages/kbn-securitysolution-lists-common/README.md new file mode 100644 index 0000000000000..4b7fbddc3ea06 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/README.md @@ -0,0 +1,20 @@ +# Security Solution Lists common package + +The package contains common files for the Lists feature. + +`common` in the name highlights that this package is intended to combine any common entities related to Lists in this package. E.g. the other `kbn-securitysolution-list-*` packages +content should be moved here while `kbn-securitysolution-io-ts-list-types` package should be +gone eventually. + +## API folder + +`api` folder contains OpenAPI schemas for Security Solution Lists feature. There are automatically generated Zod schemas and TS types for each schemas located in corresponding +`*.gen.ts` files. + +**Please add any Lists feature related schemas to this package.** + +TS types and/or Zod schemas can be imported in a plugin or another package like + +```ts +import { CreateListRequestBody } from '@kbn/securitysolution-lists-common/api'; +``` diff --git a/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts new file mode 100644 index 0000000000000..22c4a1c47bb8a --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/create_list/create_list.gen.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create list API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { + ListId, + ListName, + ListDescription, + ListType, + ListMetadata, +} from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type CreateListRequestBody = z.infer; +export const CreateListRequestBody = z.object({ + id: ListId.optional(), + name: ListName, + description: ListDescription, + type: ListType, + serializer: z.string().optional(), + deserializer: z.string().optional(), + meta: ListMetadata.optional(), + version: z.number().int().min(1).optional().default(1), +}); +export type CreateListRequestBodyInput = z.input; + +export type CreateListResponse = z.infer; +export const CreateListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml new file mode 100644 index 0000000000000..0cd635c46ff7f --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/create_list/create_list.schema.yaml @@ -0,0 +1,82 @@ +openapi: 3.0.0 +info: + title: Create list API endpoint + version: '2023-10-31' +paths: + /api/lists: + post: + x-labels: [serverless, ess] + operationId: CreateList + x-codegen-enabled: true + summary: Creates a list + tags: + - List API + requestBody: + description: List's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + name: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' + type: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListType' + serializer: + type: string + deserializer: + type: string + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' + version: + type: integer + minimum: 1 + default: 1 + required: + - name + - description + - type + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List already exists response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts b/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts new file mode 100644 index 0000000000000..b2217f2016422 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create list DS API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type CreateListIndexResponse = z.infer; +export const CreateListIndexResponse = z.object({ + acknowledged: z.boolean(), +}); diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml b/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml new file mode 100644 index 0000000000000..f42937a8885d2 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/create_list_index/create_list_index.schema.yaml @@ -0,0 +1,56 @@ +openapi: 3.0.0 +info: + title: Create list DS API endpoint + version: '2023-10-31' +paths: + /api/lists/index: + post: + x-labels: [serverless, ess] + operationId: CreateListIndex + x-codegen-enabled: true + summary: Creates necessary list data streams + tags: + - List API + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + required: [acknowledged] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List data stream exists response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.ts new file mode 100644 index 0000000000000..94e1be2171921 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Create list item API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListItemId, ListId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type CreateListItemRequestBody = z.infer; +export const CreateListItemRequestBody = z.object({ + id: ListItemId.optional(), + list_id: ListId, + value: ListItemValue, + meta: ListItemMetadata.optional(), + /** + * Determines when changes made by the request are made visible to search + */ + refresh: z.enum(['true', 'false', 'wait_for']).optional(), +}); +export type CreateListItemRequestBodyInput = z.input; + +export type CreateListItemResponse = z.infer; +export const CreateListItemResponse = ListItem; diff --git a/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml new file mode 100644 index 0000000000000..ca75b8555b9c4 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/create_list_item/create_list_item.schema.yaml @@ -0,0 +1,78 @@ +openapi: 3.0.0 +info: + title: Create list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + post: + x-labels: [serverless, ess] + operationId: CreateListItem + x-codegen-enabled: true + summary: Creates a list item + tags: + - List item API + requestBody: + description: List item's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' + list_id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + value: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' + refresh: + type: string + enum: + - 'true' + - 'false' + - wait_for + description: Determines when changes made by the request are made visible to search + required: + - list_id + - value + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List item already exists response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts new file mode 100644 index 0000000000000..fe058928eca0b --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.gen.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Delete list API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; +import { BooleanFromString } from '@kbn/zod-helpers'; + +import { ListId } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type DeleteListRequestQuery = z.infer; +export const DeleteListRequestQuery = z.object({ + /** + * List's `id` value + */ + id: ListId, + deleteReferences: BooleanFromString.optional().default(false), + ignoreReferences: BooleanFromString.optional().default(false), +}); +export type DeleteListRequestQueryInput = z.input; + +export type DeleteListResponse = z.infer; +export const DeleteListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml new file mode 100644 index 0000000000000..c116d43edd93a --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/delete_list/delete_list.schema.yaml @@ -0,0 +1,71 @@ +openapi: 3.0.0 +info: + title: Delete list API endpoint + version: '2023-10-31' +paths: + /api/lists: + delete: + x-labels: [serverless, ess] + operationId: DeleteList + x-codegen-enabled: true + summary: Deletes a list + tags: + - List API + parameters: + - name: id + in: query + required: true + description: List's `id` value + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: deleteReferences + in: query + required: false + schema: + type: boolean + default: false + - name: ignoreReferences + in: query + required: false + schema: + type: boolean + default: false + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts b/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts new file mode 100644 index 0000000000000..3be609d0b8a92 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Delete list DS API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type DeleteListIndexResponse = z.infer; +export const DeleteListIndexResponse = z.object({ + acknowledged: z.boolean(), +}); diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml b/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml new file mode 100644 index 0000000000000..c3b4969aa3283 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/delete_list_index/delete_list_index.schema.yaml @@ -0,0 +1,56 @@ +openapi: 3.0.0 +info: + title: Delete list DS API endpoint + version: '2023-10-31' +paths: + /api/lists/index: + delete: + x-labels: [serverless, ess] + operationId: DeleteListIndex + x-codegen-enabled: true + summary: Deletes list data streams + tags: + - List API + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + required: [acknowledged] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List data stream not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.ts new file mode 100644 index 0000000000000..d94b2f18d6158 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.gen.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 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Delete list item API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type DeleteListItemRequestQuery = z.infer; +export const DeleteListItemRequestQuery = z.object({ + /** + * Required if `list_id` and `value` are not specified + */ + id: ListId.optional(), + /** + * Required if `id` is not specified + */ + list_id: ListId.optional(), + /** + * Required if `id` is not specified + */ + value: z.string().optional(), + /** + * Determines when changes made by the request are made visible to search + */ + refresh: z.enum(['true', 'false', 'wait_for']).optional().default('false'), +}); +export type DeleteListItemRequestQueryInput = z.input; + +export type DeleteListItemResponse = z.infer; +export const DeleteListItemResponse = z.union([ListItem, z.array(ListItem)]); diff --git a/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml new file mode 100644 index 0000000000000..63938d313aea2 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/delete_list_item/delete_list_item.schema.yaml @@ -0,0 +1,83 @@ +openapi: 3.0.0 +info: + title: Delete list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + delete: + x-labels: [serverless, ess] + operationId: DeleteListItem + x-codegen-enabled: true + summary: Deletes a list item + tags: + - List item API + parameters: + - name: id + in: query + required: false + description: Required if `list_id` and `value` are not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: list_id + in: query + required: false + description: Required if `id` is not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: value + in: query + required: false + description: Required if `id` is not specified + schema: + type: string + - name: refresh + in: query + required: false + description: Determines when changes made by the request are made visible to search + schema: + type: string + enum: ['true', 'false', 'wait_for'] + default: 'false' + responses: + 200: + description: Successful response + content: + application/json: + schema: + oneOf: + - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + - type: array + items: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.gen.ts new file mode 100644 index 0000000000000..0e831e0887bd0 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.gen.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Export list items API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId } from '../model/list_common.gen'; + +export type ExportListItemsRequestQuery = z.infer; +export const ExportListItemsRequestQuery = z.object({ + /** + * List's id to export + */ + list_id: ListId, +}); +export type ExportListItemsRequestQueryInput = z.input; diff --git a/packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.schema.yaml new file mode 100644 index 0000000000000..26708a18a899a --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/export_list_item/export_list_item.schema.yaml @@ -0,0 +1,61 @@ +openapi: 3.0.0 +info: + title: Export list items API endpoint + version: '2023-10-31' +paths: + /api/lists/items/_export: + post: + operationId: ExportListItems + x-codegen-enabled: true + summary: Exports list items + description: Exports list item values from the specified list + tags: + - List items Import/Export API + parameters: + - name: list_id + in: query + required: true + description: List's id to export + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + responses: + 200: + description: Successful response + content: + application/ndjson: + schema: + type: string + format: binary + description: A `.txt` file containing list items from the specified list + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/find_list/find_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/find_list/find_list.gen.ts new file mode 100644 index 0000000000000..22bd50fcf0f35 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/find_list/find_list.gen.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Find lists API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '@kbn/openapi-common/schemas/primitives.gen'; +import { List } from '../model/list_schemas.gen'; + +export type FindListsCursor = z.infer; +export const FindListsCursor = NonEmptyString; + +export type FindListsFilter = z.infer; +export const FindListsFilter = NonEmptyString; + +export type FindListsRequestQuery = z.infer; +export const FindListsRequestQuery = z.object({ + /** + * The page number to return + */ + page: z.coerce.number().int().optional(), + /** + * The number of lists to return per page + */ + per_page: z.coerce.number().int().optional(), + /** + * Determines which field is used to sort the results + */ + sort_field: NonEmptyString.optional(), + /** + * Determines the sort order, which can be `desc` or `asc` + */ + sort_order: z.enum(['desc', 'asc']).optional(), + /** + * Returns the list that come after the last list returned in the previous call +(use the cursor value returned in the previous call). This parameter uses +the `tie_breaker_id` field to ensure all lists are sorted and returned correctly. + + */ + cursor: FindListsCursor.optional(), + /** + * Filters the returned results according to the value of the specified field, +using the : syntax. + + */ + filter: FindListsFilter.optional(), +}); +export type FindListsRequestQueryInput = z.input; + +export type FindListsResponse = z.infer; +export const FindListsResponse = z.object({ + data: z.array(List), + page: z.number().int().min(0), + per_page: z.number().int().min(0), + total: z.number().int().min(0), + cursor: FindListsCursor, +}); diff --git a/packages/kbn-securitysolution-lists-common/api/find_list/find_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/find_list/find_list.schema.yaml new file mode 100644 index 0000000000000..7fa5f1ac581ac --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/find_list/find_list.schema.yaml @@ -0,0 +1,119 @@ +openapi: 3.0.0 +info: + title: Find lists API endpoint + version: '2023-10-31' +paths: + /api/lists/_find: + get: + x-labels: [serverless, ess] + operationId: FindLists + x-codegen-enabled: true + summary: Finds lists + tags: + - List API + parameters: + - name: page + in: query + required: false + description: The page number to return + schema: + type: integer + - name: per_page + in: query + required: false + description: The number of lists to return per page + schema: + type: integer + - name: sort_field + in: query + required: false + description: Determines which field is used to sort the results + schema: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + - name: sort_order + in: query + required: false + description: Determines the sort order, which can be `desc` or `asc` + schema: + type: string + enum: [desc, asc] + - name: cursor + in: query + required: false + description: | + Returns the list that come after the last list returned in the previous call + (use the cursor value returned in the previous call). This parameter uses + the `tie_breaker_id` field to ensure all lists are sorted and returned correctly. + schema: + $ref: '#/components/schemas/FindListsCursor' + - name: filter + in: query + required: false + description: | + Filters the returned results according to the value of the specified field, + using the : syntax. + schema: + $ref: '#/components/schemas/FindListsFilter' + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + page: + type: integer + minimum: 0 + per_page: + type: integer + minimum: 0 + total: + type: integer + minimum: 0 + cursor: + $ref: '#/components/schemas/FindListsCursor' + required: + - data + - page + - per_page + - total + - cursor + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + FindListsCursor: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + FindListsFilter: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' diff --git a/packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.gen.ts new file mode 100644 index 0000000000000..ef23adf7a7dcd --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.gen.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Find list items API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '@kbn/openapi-common/schemas/primitives.gen'; +import { ListId } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type FindListItemsCursor = z.infer; +export const FindListItemsCursor = NonEmptyString; + +export type FindListItemsFilter = z.infer; +export const FindListItemsFilter = NonEmptyString; + +export type FindListItemsRequestQuery = z.infer; +export const FindListItemsRequestQuery = z.object({ + /** + * List's ide + */ + list_id: ListId, + /** + * The page number to return + */ + page: z.coerce.number().int().optional(), + /** + * The number of list items to return per page + */ + per_page: z.coerce.number().int().optional(), + /** + * Determines which field is used to sort the results + */ + sort_field: NonEmptyString.optional(), + /** + * Determines the sort order, which can be `desc` or `asc` + */ + sort_order: z.enum(['desc', 'asc']).optional(), + /** + * Returns the list that come after the last list returned in the previous call +(use the cursor value returned in the previous call). This parameter uses +the `tie_breaker_id` field to ensure all lists are sorted and returned correctly. + + */ + cursor: FindListItemsCursor.optional(), + /** + * Filters the returned results according to the value of the specified field, +using the : syntax. + + */ + filter: FindListItemsFilter.optional(), +}); +export type FindListItemsRequestQueryInput = z.input; + +export type FindListItemsResponse = z.infer; +export const FindListItemsResponse = z.object({ + data: z.array(ListItem), + page: z.number().int().min(0), + per_page: z.number().int().min(0), + total: z.number().int().min(0), + cursor: FindListItemsCursor, +}); diff --git a/packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.schema.yaml new file mode 100644 index 0000000000000..92dbc361b7ad2 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/find_list_item/find_list_item.schema.yaml @@ -0,0 +1,125 @@ +openapi: 3.0.0 +info: + title: Find list items API endpoint + version: '2023-10-31' +paths: + /api/lists/_find: + get: + x-labels: [serverless, ess] + operationId: FindListItems + x-codegen-enabled: true + summary: Finds list items + tags: + - List API + parameters: + - name: list_id + in: query + required: true + description: List's ide + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: page + in: query + required: false + description: The page number to return + schema: + type: integer + - name: per_page + in: query + required: false + description: The number of list items to return per page + schema: + type: integer + - name: sort_field + in: query + required: false + description: Determines which field is used to sort the results + schema: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + - name: sort_order + in: query + required: false + description: Determines the sort order, which can be `desc` or `asc` + schema: + type: string + enum: [desc, asc] + - name: cursor + in: query + required: false + description: | + Returns the list that come after the last list returned in the previous call + (use the cursor value returned in the previous call). This parameter uses + the `tie_breaker_id` field to ensure all lists are sorted and returned correctly. + schema: + $ref: '#/components/schemas/FindListItemsCursor' + - name: filter + in: query + required: false + description: | + Filters the returned results according to the value of the specified field, + using the : syntax. + schema: + $ref: '#/components/schemas/FindListItemsFilter' + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + page: + type: integer + minimum: 0 + per_page: + type: integer + minimum: 0 + total: + type: integer + minimum: 0 + cursor: + $ref: '#/components/schemas/FindListItemsCursor' + required: + - data + - page + - per_page + - total + - cursor + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + FindListItemsCursor: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + FindListItemsFilter: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' diff --git a/packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.gen.ts b/packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.gen.ts new file mode 100644 index 0000000000000..3fe6348242822 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.gen.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Get list privileges API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type ListPrivileges = z.infer; +export const ListPrivileges = z.object({ + username: z.string(), + has_all_requested: z.boolean(), + cluster: z.object({}).catchall(z.boolean()), + index: z.object({}).catchall(z.object({}).catchall(z.boolean())), + application: z.object({}).catchall(z.boolean()), +}); + +export type ListItemPrivileges = z.infer; +export const ListItemPrivileges = z.object({ + username: z.string(), + has_all_requested: z.boolean(), + cluster: z.object({}).catchall(z.boolean()), + index: z.object({}).catchall(z.object({}).catchall(z.boolean())), + application: z.object({}).catchall(z.boolean()), +}); + +export type GetListPrivilegesResponse = z.infer; +export const GetListPrivilegesResponse = z.object({ + lists: ListPrivileges, + listItems: ListItemPrivileges, + is_authenticated: z.boolean(), +}); diff --git a/packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.schema.yaml b/packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.schema.yaml new file mode 100644 index 0000000000000..729da9b8f62a8 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/get_list_privileges/get_list_privileges.schema.yaml @@ -0,0 +1,115 @@ +openapi: 3.0.0 +info: + title: Get list privileges API endpoint + version: '2023-10-31' +paths: + /api/lists/privileges: + get: + x-labels: [serverless, ess] + operationId: GetListPrivileges + x-codegen-enabled: true + summary: Gets list privileges + tags: + - List API + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + lists: + $ref: '#/components/schemas/ListPrivileges' + listItems: + $ref: '#/components/schemas/ListItemPrivileges' + is_authenticated: + type: boolean + required: + - lists + - listItems + - is_authenticated + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + +components: + schemas: + ListPrivileges: + type: object + properties: + username: + type: string + has_all_requested: + type: boolean + cluster: + type: object + additionalProperties: + type: boolean + index: + type: object + additionalProperties: + type: object + additionalProperties: + type: boolean + application: + type: object + additionalProperties: + type: boolean + required: + - username + - has_all_requested + - cluster + - index + - application + + ListItemPrivileges: + type: object + properties: + username: + type: string + has_all_requested: + type: boolean + cluster: + type: object + additionalProperties: + type: boolean + index: + type: object + additionalProperties: + type: object + additionalProperties: + type: boolean + application: + type: object + additionalProperties: + type: boolean + required: + - username + - has_all_requested + - cluster + - index + - application diff --git a/packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.gen.ts new file mode 100644 index 0000000000000..5748e6a78e2c0 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.gen.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Import list items API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId, ListType } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type ImportListItemsRequestQuery = z.infer; +export const ImportListItemsRequestQuery = z.object({ + /** + * List's id. + +Required when importing to an existing list. + + */ + list_id: ListId.optional(), + /** + * Type of the importing list. + +Required when importing a new list that is `list_id` is not specified. + + */ + type: ListType.optional(), + serializer: z.string().optional(), + deserializer: z.string().optional(), + /** + * Determines when changes made by the request are made visible to search + */ + refresh: z.enum(['true', 'false', 'wait_for']).optional(), +}); +export type ImportListItemsRequestQueryInput = z.input; + +export type ImportListItemsResponse = z.infer; +export const ImportListItemsResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.schema.yaml new file mode 100644 index 0000000000000..561d52587aad2 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/import_list_item/import_list_item.schema.yaml @@ -0,0 +1,102 @@ +openapi: 3.0.0 +info: + title: Import list items API endpoint + version: '2023-10-31' +paths: + /api/lists/items/_import: + post: + operationId: ImportListItems + x-codegen-enabled: true + summary: Imports list items + description: | + Imports a list of items from a `.txt` or `.csv` file. The maximum file size is 9 million bytes. + + You can import items to a new or existing list. + tags: + - List items Import/Export API + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + description: A `.txt` or `.csv` file containing newline separated list items + parameters: + - name: list_id + in: query + required: false + description: | + List's id. + + Required when importing to an existing list. + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: type + in: query + required: false + description: | + Type of the importing list. + + Required when importing a new list that is `list_id` is not specified. + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListType' + - name: serializer + in: query + required: false + schema: + type: string + - name: deserializer + in: query + required: false + schema: + type: string + - name: refresh + in: query + required: false + description: Determines when changes made by the request are made visible to search + schema: + type: string + enum: ['true', 'false', 'wait_for'] + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 409: + description: List with specified list_id does not exist response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/index.ts b/packages/kbn-securitysolution-lists-common/api/index.ts new file mode 100644 index 0000000000000..7b1fb1508653d --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +export * from './model/list_common.gen'; +export * from './model/list_schemas.gen'; +export * from './create_list_index/create_list_index.gen'; +export * from './create_list_item/create_list_item.gen'; +export * from './create_list/create_list.gen'; +export * from './delete_list_index/delete_list_index.gen'; +export * from './delete_list_item/delete_list_item.gen'; +export * from './delete_list/delete_list.gen'; +export * from './find_list_item/find_list_item.gen'; +export * from './find_list/find_list.gen'; +export * from './export_list_item/export_list_item.gen'; +export * from './import_list_item/import_list_item.gen'; +export * from './patch_list_item/patch_list_item.gen'; +export * from './patch_list/patch_list.gen'; +export * from './read_list_index/read_list_index.gen'; +export * from './read_list_item/read_list_item.gen'; +export * from './read_list/read_list.gen'; +export * from './update_list_item/update_list_item.gen'; +export * from './update_list/update_list.gen'; diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts b/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.ts new file mode 100644 index 0000000000000..f4a6a007fed9b --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/model/list_common.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Common List Attributes + * version: not applicable + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '@kbn/openapi-common/schemas/primitives.gen'; + +export type ListId = z.infer; +export const ListId = NonEmptyString; + +export type ListType = z.infer; +export const ListType = z.enum([ + 'binary', + 'boolean', + 'byte', + 'date', + 'date_nanos', + 'date_range', + 'double', + 'double_range', + 'float', + 'float_range', + 'geo_point', + 'geo_shape', + 'half_float', + 'integer', + 'integer_range', + 'ip', + 'ip_range', + 'keyword', + 'long', + 'long_range', + 'shape', + 'short', + 'text', +]); +export type ListTypeEnum = typeof ListType.enum; +export const ListTypeEnum = ListType.enum; + +export type ListName = z.infer; +export const ListName = NonEmptyString; + +export type ListDescription = z.infer; +export const ListDescription = NonEmptyString; + +export type ListMetadata = z.infer; +export const ListMetadata = z.object({}).catchall(z.unknown()); + +export type ListItemId = z.infer; +export const ListItemId = NonEmptyString; + +export type ListItemValue = z.infer; +export const ListItemValue = NonEmptyString; + +export type ListItemDescription = z.infer; +export const ListItemDescription = NonEmptyString; + +export type ListItemMetadata = z.infer; +export const ListItemMetadata = z.object({}).catchall(z.unknown()); diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml b/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml new file mode 100644 index 0000000000000..6fb160105bb5a --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/model/list_common.schema.yaml @@ -0,0 +1,59 @@ +openapi: 3.0.0 +info: + title: Common List Attributes + version: 'not applicable' +paths: {} +components: + schemas: + ListId: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListType: + type: string + enum: + - binary + - boolean + - byte + - date + - date_nanos + - date_range + - double + - double_range + - float + - float_range + - geo_point + - geo_shape + - half_float + - integer + - integer_range + - ip + - ip_range + - keyword + - long + - long_range + - shape + - short + - text + + ListName: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListDescription: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListMetadata: + type: object + additionalProperties: true + + ListItemId: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListItemValue: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListItemDescription: + $ref: '../../../kbn-openapi-common/schemas/primitives.schema.yaml#/components/schemas/NonEmptyString' + + ListItemMetadata: + type: object + additionalProperties: true diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts b/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts new file mode 100644 index 0000000000000..c70278df938ce --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/model/list_schemas.gen.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: List Schemas + * version: not applicable + */ + +import { z } from 'zod'; + +import { + ListId, + ListType, + ListName, + ListDescription, + ListMetadata, + ListItemId, + ListItemValue, + ListItemMetadata, +} from './list_common.gen'; + +export type List = z.infer; +export const List = z.object({ + id: ListId, + type: ListType, + name: ListName, + description: ListDescription, + serializer: z.string().optional(), + deserializer: z.string().optional(), + immutable: z.boolean(), + meta: ListMetadata.optional(), + '@timestamp': z.string().datetime().optional(), + version: z.number().int().min(1), + _version: z.string().optional(), + tie_breaker_id: z.string(), + created_at: z.string().datetime(), + created_by: z.string(), + updated_at: z.string().datetime(), + updated_by: z.string(), +}); + +export type ListItem = z.infer; +export const ListItem = z.object({ + id: ListItemId, + type: ListType, + list_id: ListId, + value: ListItemValue, + serializer: z.string().optional(), + deserializer: z.string().optional(), + meta: ListItemMetadata.optional(), + '@timestamp': z.string().datetime().optional(), + _version: z.string().optional(), + tie_breaker_id: z.string(), + created_at: z.string().datetime(), + created_by: z.string(), + updated_at: z.string().datetime(), + updated_by: z.string(), +}); diff --git a/packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml b/packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml new file mode 100644 index 0000000000000..838dc5e4edea0 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/model/list_schemas.schema.yaml @@ -0,0 +1,103 @@ +openapi: 3.0.0 +info: + title: List Schemas + version: 'not applicable' +paths: {} +components: + schemas: + List: + type: object + properties: + id: + $ref: './list_common.schema.yaml#/components/schemas/ListId' + type: + $ref: './list_common.schema.yaml#/components/schemas/ListType' + name: + $ref: './list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: './list_common.schema.yaml#/components/schemas/ListDescription' + serializer: + type: string + deserializer: + type: string + immutable: + type: boolean + meta: + $ref: './list_common.schema.yaml#/components/schemas/ListMetadata' + '@timestamp': + type: string + format: date-time + version: + type: integer + minimum: 1 + _version: + type: string + tie_breaker_id: + type: string + created_at: + type: string + format: date-time + created_by: + type: string + updated_at: + type: string + format: date-time + updated_by: + type: string + required: + - id + - type + - name + - description + - immutable + - version + - tie_breaker_id + - created_at + - created_by + - updated_at + - updated_by + + ListItem: + type: object + properties: + id: + $ref: './list_common.schema.yaml#/components/schemas/ListItemId' + type: + $ref: './list_common.schema.yaml#/components/schemas/ListType' + list_id: + $ref: './list_common.schema.yaml#/components/schemas/ListId' + value: + $ref: './list_common.schema.yaml#/components/schemas/ListItemValue' + serializer: + type: string + deserializer: + type: string + meta: + $ref: './list_common.schema.yaml#/components/schemas/ListItemMetadata' + '@timestamp': + type: string + format: date-time + _version: + type: string + tie_breaker_id: + type: string + created_at: + type: string + format: date-time + created_by: + type: string + updated_at: + type: string + format: date-time + updated_by: + type: string + required: + - id + - type + - list_id + - value + - tie_breaker_id + - created_at + - created_by + - updated_at + - updated_by diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.ts new file mode 100644 index 0000000000000..47eeb87d0f5d4 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Patch list API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId, ListName, ListDescription, ListMetadata } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type PatchListRequestBody = z.infer; +export const PatchListRequestBody = z.object({ + id: ListId, + name: ListName.optional(), + description: ListDescription.optional(), + meta: ListMetadata.optional(), + version: z.number().int().min(1).optional(), + _version: z.string().optional(), +}); +export type PatchListRequestBodyInput = z.input; + +export type PatchListResponse = z.infer; +export const PatchListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml new file mode 100644 index 0000000000000..cae09887db312 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/patch_list/patch_list.schema.yaml @@ -0,0 +1,75 @@ +openapi: 3.0.0 +info: + title: Patch list API endpoint + version: '2023-10-31' +paths: + /api/lists: + patch: + x-labels: [serverless, ess] + operationId: PatchList + x-codegen-enabled: true + summary: Patches a list + tags: + - List API + requestBody: + description: List's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + name: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' + version: + type: integer + minimum: 1 + _version: + type: string + required: + - id + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.ts new file mode 100644 index 0000000000000..ce29d68bed7a7 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Patch list item API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListItemId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type PatchListItemRequestBody = z.infer; +export const PatchListItemRequestBody = z.object({ + id: ListItemId, + value: ListItemValue.optional(), + meta: ListItemMetadata.optional(), + _version: z.string().optional(), + /** + * Determines when changes made by the request are made visible to search + */ + refresh: z.enum(['true', 'false', 'wait_for']).optional(), +}); +export type PatchListItemRequestBodyInput = z.input; + +export type PatchListItemResponse = z.infer; +export const PatchListItemResponse = ListItem; diff --git a/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml new file mode 100644 index 0000000000000..36ca55c7ae065 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/patch_list_item/patch_list_item.schema.yaml @@ -0,0 +1,77 @@ +openapi: 3.0.0 +info: + title: Patch list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + patch: + x-labels: [serverless, ess] + operationId: PatchListItem + x-codegen-enabled: true + summary: Patches a list item + tags: + - List item API + requestBody: + description: List item's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' + value: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' + _version: + type: string + refresh: + type: string + enum: + - 'true' + - 'false' + - wait_for + description: Determines when changes made by the request are made visible to search + required: + - id + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.ts new file mode 100644 index 0000000000000..2ae0eb6f6c91b --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/read_list/read_list.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Get list API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type GetListRequestQuery = z.infer; +export const GetListRequestQuery = z.object({ + /** + * List's `id` value + */ + id: ListId, +}); +export type GetListRequestQueryInput = z.input; + +export type GetListResponse = z.infer; +export const GetListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml new file mode 100644 index 0000000000000..4a2ae5d2cd42c --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/read_list/read_list.schema.yaml @@ -0,0 +1,59 @@ +openapi: 3.0.0 +info: + title: Get list API endpoint + version: '2023-10-31' +paths: + /api/lists: + get: + x-labels: [serverless, ess] + operationId: GetList + x-codegen-enabled: true + summary: Retrieves a list using its id field + tags: + - List API + parameters: + - name: id + in: query + required: true + description: List's `id` value + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts b/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.ts new file mode 100644 index 0000000000000..c25105f038636 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.gen.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 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Get list DS existence status API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +export type GetListIndexResponse = z.infer; +export const GetListIndexResponse = z.object({ + list_index: z.boolean(), + list_item_index: z.boolean(), +}); diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml b/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml new file mode 100644 index 0000000000000..accef8b58411e --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/read_list_index/read_list_index.schema.yaml @@ -0,0 +1,58 @@ +openapi: 3.0.0 +info: + title: Get list DS existence status API endpoint + version: '2023-10-31' +paths: + /api/lists/index: + get: + x-labels: [serverless, ess] + operationId: GetListIndex + x-codegen-enabled: true + summary: Get list data stream existence status + tags: + - List API + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + list_index: + type: boolean + list_item_index: + type: boolean + required: [list_index, list_item_index] + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List data stream(s) not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts new file mode 100644 index 0000000000000..e9f5b9eef9cf8 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.gen.ts @@ -0,0 +1,41 @@ +/* + * Copyright 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Get list item API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type GetListItemRequestQuery = z.infer; +export const GetListItemRequestQuery = z.object({ + /** + * Required if `list_id` and `value` are not specified + */ + id: ListId.optional(), + /** + * Required if `id` is not specified + */ + list_id: ListId.optional(), + /** + * Required if `id` is not specified + */ + value: z.string().optional(), +}); +export type GetListItemRequestQueryInput = z.input; + +export type GetListItemResponse = z.infer; +export const GetListItemResponse = z.union([ListItem, z.array(ListItem)]); diff --git a/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml new file mode 100644 index 0000000000000..3a651617163aa --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/read_list_item/read_list_item.schema.yaml @@ -0,0 +1,75 @@ +openapi: 3.0.0 +info: + title: Get list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + get: + x-labels: [serverless, ess] + operationId: GetListItem + x-codegen-enabled: true + summary: Gets a list item + tags: + - List item API + parameters: + - name: id + in: query + required: false + description: Required if `list_id` and `value` are not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: list_id + in: query + required: false + description: Required if `id` is not specified + schema: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + - name: value + in: query + required: false + description: Required if `id` is not specified + schema: + type: string + responses: + 200: + description: Successful response + content: + application/json: + schema: + oneOf: + - $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + - type: array + items: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts b/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.ts new file mode 100644 index 0000000000000..833239a7eb82b --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/update_list/update_list.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Update list API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListId, ListName, ListDescription, ListMetadata } from '../model/list_common.gen'; +import { List } from '../model/list_schemas.gen'; + +export type UpdateListRequestBody = z.infer; +export const UpdateListRequestBody = z.object({ + id: ListId, + name: ListName, + description: ListDescription, + meta: ListMetadata.optional(), + version: z.number().int().min(1).optional(), + _version: z.string().optional(), +}); +export type UpdateListRequestBodyInput = z.input; + +export type UpdateListResponse = z.infer; +export const UpdateListResponse = List; diff --git a/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml b/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml new file mode 100644 index 0000000000000..d25b21157c725 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/update_list/update_list.schema.yaml @@ -0,0 +1,77 @@ +openapi: 3.0.0 +info: + title: Update list API endpoint + version: '2023-10-31' +paths: + /api/lists: + put: + x-labels: [serverless, ess] + operationId: UpdateList + x-codegen-enabled: true + summary: Updates a list + tags: + - List API + requestBody: + description: List's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListId' + name: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListName' + description: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListDescription' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListMetadata' + version: + type: integer + minimum: 1 + _version: + type: string + required: + - id + - name + - description + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/List' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts b/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.ts new file mode 100644 index 0000000000000..069c101beaaf4 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Update list item API endpoint + * version: 2023-10-31 + */ + +import { z } from 'zod'; + +import { ListItemId, ListItemValue, ListItemMetadata } from '../model/list_common.gen'; +import { ListItem } from '../model/list_schemas.gen'; + +export type UpdateListItemRequestBody = z.infer; +export const UpdateListItemRequestBody = z.object({ + id: ListItemId, + value: ListItemValue, + meta: ListItemMetadata.optional(), + _version: z.string().optional(), +}); +export type UpdateListItemRequestBodyInput = z.input; + +export type UpdateListItemResponse = z.infer; +export const UpdateListItemResponse = ListItem; diff --git a/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml b/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml new file mode 100644 index 0000000000000..21df82f4ba40a --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/api/update_list_item/update_list_item.schema.yaml @@ -0,0 +1,71 @@ +openapi: 3.0.0 +info: + title: Update list item API endpoint + version: '2023-10-31' +paths: + /api/lists/items: + put: + x-labels: [serverless, ess] + operationId: UpdateListItem + x-codegen-enabled: true + summary: Updates a list item + tags: + - List item API + requestBody: + description: List item's properties + required: true + content: + application/json: + schema: + type: object + properties: + id: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemId' + value: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemValue' + meta: + $ref: '../model/list_common.schema.yaml#/components/schemas/ListItemMetadata' + _version: + type: string + required: + - id + - value + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: '../model/list_schemas.schema.yaml#/components/schemas/ListItem' + 400: + description: Invalid input data response + content: + application/json: + schema: + oneOf: + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + - $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 401: + description: Unsuccessful authentication response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 403: + description: Not enough privileges response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/PlatformErrorResponse' + 404: + description: List item not found response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' + 500: + description: Internal server error response + content: + application/json: + schema: + $ref: '../../../kbn-openapi-common/schemas/error_responses.schema.yaml#/components/schemas/SiemErrorResponse' diff --git a/packages/kbn-securitysolution-lists-common/kibana.jsonc b/packages/kbn-securitysolution-lists-common/kibana.jsonc new file mode 100644 index 0000000000000..614314f10e8b4 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-lists-common", + "owner": "@elastic/security-detection-engine" +} diff --git a/packages/kbn-securitysolution-lists-common/package.json b/packages/kbn-securitysolution-lists-common/package.json new file mode 100644 index 0000000000000..298f0e47bb10f --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/package.json @@ -0,0 +1,10 @@ +{ + "description": "Security Solution Lists common package", + "license": "SSPL-1.0 OR Elastic License 2.0", + "name": "@kbn/securitysolution-lists-common", + "private": true, + "version": "1.0.0", + "scripts": { + "openapi:generate": "node scripts/openapi_generate" + } +} diff --git a/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js b/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js new file mode 100644 index 0000000000000..8580994b16859 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/scripts/openapi_generate.js @@ -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 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. + */ + +require('../../../src/setup_node_env'); +const { resolve } = require('path'); +const { generate } = require('@kbn/openapi-generator'); + +const ROOT = resolve(__dirname, '..'); + +(async () => { + await generate({ + title: 'OpenAPI Lists API Schemas', + rootDir: ROOT, + sourceGlob: './**/*.schema.yaml', + templateName: 'zod_operation_schema', + }); +})(); diff --git a/packages/kbn-securitysolution-lists-common/tsconfig.json b/packages/kbn-securitysolution-lists-common/tsconfig.json new file mode 100644 index 0000000000000..b6a14b40363c7 --- /dev/null +++ b/packages/kbn-securitysolution-lists-common/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "exclude": ["target/**/*"], + "extends": "../../tsconfig.base.json", + "include": ["**/*.ts"], + "kbn_references": ["@kbn/zod-helpers", "@kbn/openapi-common"] +} diff --git a/packages/kbn-zod-helpers/index.ts b/packages/kbn-zod-helpers/index.ts index d8a62f58686b2..e3b0f4e35a19d 100644 --- a/packages/kbn-zod-helpers/index.ts +++ b/packages/kbn-zod-helpers/index.ts @@ -14,3 +14,4 @@ export * from './src/is_valid_date_math'; export * from './src/required_optional'; export * from './src/safe_parse_result'; export * from './src/stringify_zod_error'; +export * from './src/build_route_validation_with_zod'; diff --git a/packages/kbn-zod-helpers/src/build_route_validation_with_zod.ts b/packages/kbn-zod-helpers/src/build_route_validation_with_zod.ts new file mode 100644 index 0000000000000..a72eb96d3b968 --- /dev/null +++ b/packages/kbn-zod-helpers/src/build_route_validation_with_zod.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { TypeOf, ZodType } from 'zod'; +import type { RouteValidationFunction, RouteValidationResultFactory } from '@kbn/core/server'; +import { stringifyZodError } from './stringify_zod_error'; + +/** + * Zod validation factory for Kibana route's request validation. + * It allows to pass a Zod schema for parameters, query and/or body validation. + * + * Example: + * + * ```ts + * router.versioned + * .post({ + * access: 'public', + * path: MY_URL, + * }) + * .addVersion( + * { + * version: 'my-version', + * validate: { + * request: { + * params: buildRouteValidationWithZod(MyRequestParamsZodSchema), + * query: buildRouteValidationWithZod(MyRequestQueryZodSchema), + * body: buildRouteValidationWithZod(MyRequestBodyZodSchema), + * }, + * }, + * }, + * ``` + */ +export function buildRouteValidationWithZod>( + schema: ZodSchema +): RouteValidationFunction { + return (inputValue: unknown, validationResult: RouteValidationResultFactory) => { + const decoded = schema.safeParse(inputValue); + + return decoded.success + ? validationResult.ok(decoded.data) + : validationResult.badRequest(stringifyZodError(decoded.error)); + }; +} diff --git a/packages/kbn-zod-helpers/tsconfig.json b/packages/kbn-zod-helpers/tsconfig.json index 0b3850da21158..fbe3b91a89493 100644 --- a/packages/kbn-zod-helpers/tsconfig.json +++ b/packages/kbn-zod-helpers/tsconfig.json @@ -6,7 +6,5 @@ "exclude": ["target/**/*"], "extends": "../../tsconfig.base.json", "include": ["**/*.ts"], - "kbn_references": [ - "@kbn/datemath", - ] + "kbn_references": ["@kbn/datemath", "@kbn/core"] } diff --git a/tsconfig.base.json b/tsconfig.base.json index bd6380bf501c4..ea18fe456af85 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1238,6 +1238,8 @@ "@kbn/open-telemetry-instrumented-plugin/*": ["test/common/plugins/otel_metrics/*"], "@kbn/openapi-bundler": ["packages/kbn-openapi-bundler"], "@kbn/openapi-bundler/*": ["packages/kbn-openapi-bundler/*"], + "@kbn/openapi-common": ["packages/kbn-openapi-common"], + "@kbn/openapi-common/*": ["packages/kbn-openapi-common/*"], "@kbn/openapi-generator": ["packages/kbn-openapi-generator"], "@kbn/openapi-generator/*": ["packages/kbn-openapi-generator/*"], "@kbn/optimizer": ["packages/kbn-optimizer"], @@ -1498,6 +1500,8 @@ "@kbn/securitysolution-list-hooks/*": ["packages/kbn-securitysolution-list-hooks/*"], "@kbn/securitysolution-list-utils": ["packages/kbn-securitysolution-list-utils"], "@kbn/securitysolution-list-utils/*": ["packages/kbn-securitysolution-list-utils/*"], + "@kbn/securitysolution-lists-common": ["packages/kbn-securitysolution-lists-common"], + "@kbn/securitysolution-lists-common/*": ["packages/kbn-securitysolution-lists-common/*"], "@kbn/securitysolution-rules": ["packages/kbn-securitysolution-rules"], "@kbn/securitysolution-rules/*": ["packages/kbn-securitysolution-rules/*"], "@kbn/securitysolution-t-grid": ["packages/kbn-securitysolution-t-grid"], diff --git a/x-pack/plugins/lists/common/api/index.ts b/x-pack/plugins/lists/common/api/index.ts index 1d76a041d2824..1cbbeba219078 100644 --- a/x-pack/plugins/lists/common/api/index.ts +++ b/x-pack/plugins/lists/common/api/index.ts @@ -27,20 +27,4 @@ export * from './exceptions/summary_exception_list/summary_exception_list_route' export * from './exceptions/update_endpoint_list_item/update_endpoint_list_item_route'; export * from './exceptions/update_exception_list_item/update_exception_list_item_route'; export * from './exceptions/update_exception_list/update_exception_list_route'; -export * from './values/create_list_index/create_list_index_route'; -export * from './values/create_list_item/create_list_item_route'; -export * from './values/create_list/create_list_route'; -export * from './values/delete_list_index/delete_list_index_route'; -export * from './values/delete_list_item/delete_list_item_route'; -export * from './values/delete_list/delete_list_route'; -export * from './values/find_list_item/find_list_item_route'; -export * from './values/find_list/find_list_route'; export * from './values/find_lists_by_size/find_lists_by_size_route'; -export * from './values/import_list_item/import_list_item_route'; -export * from './values/patch_list_item/patch_list_item_route'; -export * from './values/patch_list/patch_list_route'; -export * from './values/read_list_index/read_list_index_route'; -export * from './values/read_list_item/read_list_item_route'; -export * from './values/read_list/read_list_route'; -export * from './values/update_list_item/update_list_item_route'; -export * from './values/update_list/update_list_route'; diff --git a/x-pack/plugins/lists/common/api/values/create_list/create_list_route.ts b/x-pack/plugins/lists/common/api/values/create_list/create_list_route.ts deleted file mode 100644 index 71dc2eecde8ea..0000000000000 --- a/x-pack/plugins/lists/common/api/values/create_list/create_list_route.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 { - CreateListSchemaDecoded, - createListSchema, - listSchema, -} from '@kbn/securitysolution-io-ts-list-types'; - -export { createListSchema as createListRequest, listSchema as createListResponse }; -export type { CreateListSchemaDecoded as CreateListRequestDecoded }; diff --git a/x-pack/plugins/lists/common/api/values/create_list_index/create_list_index_route.ts b/x-pack/plugins/lists/common/api/values/create_list_index/create_list_index_route.ts deleted file mode 100644 index 85e094b273e13..0000000000000 --- a/x-pack/plugins/lists/common/api/values/create_list_index/create_list_index_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { acknowledgeSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { acknowledgeSchema as createListIndexResponse }; diff --git a/x-pack/plugins/lists/common/api/values/create_list_item/create_list_item_route.ts b/x-pack/plugins/lists/common/api/values/create_list_item/create_list_item_route.ts deleted file mode 100644 index 70cef948d6cf1..0000000000000 --- a/x-pack/plugins/lists/common/api/values/create_list_item/create_list_item_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { createListItemSchema, listItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { createListItemSchema as createListItemRequest, listItemSchema as createListItemResponse }; diff --git a/x-pack/plugins/lists/common/api/values/delete_list/delete_list_route.ts b/x-pack/plugins/lists/common/api/values/delete_list/delete_list_route.ts deleted file mode 100644 index b360d3e5c6880..0000000000000 --- a/x-pack/plugins/lists/common/api/values/delete_list/delete_list_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { deleteListSchema, listSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { deleteListSchema as deleteListRequestQuery, listSchema as deleteListResponse }; diff --git a/x-pack/plugins/lists/common/api/values/delete_list_index/delete_list_index_route.ts b/x-pack/plugins/lists/common/api/values/delete_list_index/delete_list_index_route.ts deleted file mode 100644 index 2423ebd6bea60..0000000000000 --- a/x-pack/plugins/lists/common/api/values/delete_list_index/delete_list_index_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { acknowledgeSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { acknowledgeSchema as deleteListIndexResponse }; diff --git a/x-pack/plugins/lists/common/api/values/delete_list_item/delete_list_item_route.ts b/x-pack/plugins/lists/common/api/values/delete_list_item/delete_list_item_route.ts deleted file mode 100644 index 418401d2b6c17..0000000000000 --- a/x-pack/plugins/lists/common/api/values/delete_list_item/delete_list_item_route.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - deleteListItemSchema, - listItemArraySchema, - listItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; - -export { - deleteListItemSchema as deleteListItemRequestQuery, - listItemSchema as deleteListItemResponse, - listItemArraySchema as deleteListItemArrayResponse, -}; diff --git a/x-pack/plugins/lists/common/api/values/find_list/find_list_route.ts b/x-pack/plugins/lists/common/api/values/find_list/find_list_route.ts deleted file mode 100644 index 8c3301daed3c9..0000000000000 --- a/x-pack/plugins/lists/common/api/values/find_list/find_list_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { findListSchema, foundListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { findListSchema as findListRequestQuery, foundListSchema as findListResponse }; diff --git a/x-pack/plugins/lists/common/api/values/find_list_item/find_list_item_route.ts b/x-pack/plugins/lists/common/api/values/find_list_item/find_list_item_route.ts deleted file mode 100644 index b9d4d93ccb340..0000000000000 --- a/x-pack/plugins/lists/common/api/values/find_list_item/find_list_item_route.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - FindListItemSchemaDecoded, - findListItemSchema, - foundListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; - -export { - findListItemSchema as findListItemRequestQuery, - foundListItemSchema as findListItemResponse, -}; -export type { FindListItemSchemaDecoded as FindListItemRequestQueryDecoded }; diff --git a/x-pack/plugins/lists/common/api/values/import_list_item/import_list_item_route.ts b/x-pack/plugins/lists/common/api/values/import_list_item/import_list_item_route.ts deleted file mode 100644 index 3ea57eda532fc..0000000000000 --- a/x-pack/plugins/lists/common/api/values/import_list_item/import_list_item_route.ts +++ /dev/null @@ -1,13 +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 { importListItemQuerySchema, listSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { - importListItemQuerySchema as importListItemRequestQuery, - listSchema as importListItemResponse, -}; diff --git a/x-pack/plugins/lists/common/api/values/patch_list/patch_list_route.ts b/x-pack/plugins/lists/common/api/values/patch_list/patch_list_route.ts deleted file mode 100644 index 8821658c5b23a..0000000000000 --- a/x-pack/plugins/lists/common/api/values/patch_list/patch_list_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { listSchema, patchListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { patchListSchema as patchListRequest, listSchema as patchListResponse }; diff --git a/x-pack/plugins/lists/common/api/values/patch_list_item/patch_list_item_route.ts b/x-pack/plugins/lists/common/api/values/patch_list_item/patch_list_item_route.ts deleted file mode 100644 index 12b4bd36e968e..0000000000000 --- a/x-pack/plugins/lists/common/api/values/patch_list_item/patch_list_item_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { listItemSchema, patchListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { patchListItemSchema as patchListItemRequest, listItemSchema as patchListItemResponse }; diff --git a/x-pack/plugins/lists/common/api/values/read_list/read_list_route.ts b/x-pack/plugins/lists/common/api/values/read_list/read_list_route.ts deleted file mode 100644 index be13d604f57c5..0000000000000 --- a/x-pack/plugins/lists/common/api/values/read_list/read_list_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { listSchema, readListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { readListSchema as readListRequestQuery, listSchema as readListResponse }; diff --git a/x-pack/plugins/lists/common/api/values/read_list_index/read_list_index_route.ts b/x-pack/plugins/lists/common/api/values/read_list_index/read_list_index_route.ts deleted file mode 100644 index 772d042b7e11c..0000000000000 --- a/x-pack/plugins/lists/common/api/values/read_list_index/read_list_index_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { listItemIndexExistSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { listItemIndexExistSchema as readListIndexResponse }; diff --git a/x-pack/plugins/lists/common/api/values/read_list_item/read_list_item_route.ts b/x-pack/plugins/lists/common/api/values/read_list_item/read_list_item_route.ts deleted file mode 100644 index 0b67159ceaf03..0000000000000 --- a/x-pack/plugins/lists/common/api/values/read_list_item/read_list_item_route.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - listItemArraySchema, - listItemSchema, - readListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; - -export { - readListItemSchema as readListItemRequestQuery, - listItemSchema as readListItemResponse, - listItemArraySchema as readListItemArrayResponse, -}; diff --git a/x-pack/plugins/lists/common/api/values/update_list/update_list_route.ts b/x-pack/plugins/lists/common/api/values/update_list/update_list_route.ts deleted file mode 100644 index 801e9784ac80d..0000000000000 --- a/x-pack/plugins/lists/common/api/values/update_list/update_list_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { listSchema, updateListSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { updateListSchema as updateListRequest, listSchema as updateListResponse }; diff --git a/x-pack/plugins/lists/common/api/values/update_list_item/update_list_item_route.ts b/x-pack/plugins/lists/common/api/values/update_list_item/update_list_item_route.ts deleted file mode 100644 index 9b512e61f464e..0000000000000 --- a/x-pack/plugins/lists/common/api/values/update_list_item/update_list_item_route.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { listItemSchema, updateListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; - -export { updateListItemSchema as updateListItemRequest, listItemSchema as updateListItemResponse }; diff --git a/x-pack/plugins/lists/common/schemas/request/create_list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/create_list_schema.mock.ts index 117659423103d..57dae64930dc5 100644 --- a/x-pack/plugins/lists/common/schemas/request/create_list_schema.mock.ts +++ b/x-pack/plugins/lists/common/schemas/request/create_list_schema.mock.ts @@ -5,11 +5,11 @@ * 2.0. */ -import type { CreateListSchema } from '@kbn/securitysolution-io-ts-list-types'; +import type { CreateListRequestBodyInput } from '@kbn/securitysolution-lists-common/api'; import { DESCRIPTION, LIST_ID, META, NAME, TYPE, VERSION } from '../../constants.mock'; -export const getCreateListSchemaMock = (): CreateListSchema => ({ +export const getCreateListSchemaMock = (): CreateListRequestBodyInput => ({ description: DESCRIPTION, deserializer: undefined, id: LIST_ID, @@ -23,7 +23,7 @@ export const getCreateListSchemaMock = (): CreateListSchema => ({ /** * Useful for end to end tests and other mechanisms which want to fill in the values */ -export const getCreateMinimalListSchemaMock = (): CreateListSchema => ({ +export const getCreateMinimalListSchemaMock = (): CreateListRequestBodyInput => ({ description: DESCRIPTION, id: LIST_ID, name: NAME, @@ -33,7 +33,7 @@ export const getCreateMinimalListSchemaMock = (): CreateListSchema => ({ /** * Useful for end to end tests and other mechanisms which want to fill in the values */ -export const getCreateMinimalListSchemaMockWithoutId = (): CreateListSchema => ({ +export const getCreateMinimalListSchemaMockWithoutId = (): CreateListRequestBodyInput => ({ description: DESCRIPTION, name: NAME, type: TYPE, diff --git a/x-pack/plugins/lists/common/schemas/request/update_list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/update_list_schema.mock.ts index d38744a35a6cb..564c79e67a2bb 100644 --- a/x-pack/plugins/lists/common/schemas/request/update_list_schema.mock.ts +++ b/x-pack/plugins/lists/common/schemas/request/update_list_schema.mock.ts @@ -5,11 +5,11 @@ * 2.0. */ -import type { UpdateListSchema } from '@kbn/securitysolution-io-ts-list-types'; +import type { UpdateListRequestBody } from '@kbn/securitysolution-lists-common/api'; import { DESCRIPTION, LIST_ID, META, NAME, _VERSION } from '../../constants.mock'; -export const getUpdateListSchemaMock = (): UpdateListSchema => ({ +export const getUpdateListSchemaMock = (): UpdateListRequestBody => ({ _version: _VERSION, description: DESCRIPTION, id: LIST_ID, @@ -21,7 +21,7 @@ export const getUpdateListSchemaMock = (): UpdateListSchema => ({ * Useful for end to end tests and other mechanisms which want to fill in the values * after doing a get of the structure. */ -export const getUpdateMinimalListSchemaMock = (): UpdateListSchema => ({ +export const getUpdateMinimalListSchemaMock = (): UpdateListRequestBody => ({ description: DESCRIPTION, id: LIST_ID, name: NAME, diff --git a/x-pack/plugins/lists/server/routes/list/create_list_route.ts b/x-pack/plugins/lists/server/routes/list/create_list_route.ts index 063056461c20c..3b0e80aa7ee7e 100644 --- a/x-pack/plugins/lists/server/routes/list/create_list_route.ts +++ b/x-pack/plugins/lists/server/routes/list/create_list_route.ts @@ -5,17 +5,13 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { CreateListRequestBody, CreateListResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { - CreateListRequestDecoded, - createListRequest, - createListResponse, -} from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const createListRoute = (router: ListsPluginRouter): void => { @@ -31,9 +27,7 @@ export const createListRoute = (router: ListsPluginRouter): void => { { validate: { request: { - body: buildRouteValidation( - createListRequest - ), + body: buildRouteValidationWithZod(CreateListRequestBody), }, }, version: '2023-10-31', @@ -77,12 +71,8 @@ export const createListRoute = (router: ListsPluginRouter): void => { type, version, }); - const [validated, errors] = validate(list, createListResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + + return response.ok({ body: CreateListResponse.parse(list) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list/delete_list_route.ts b/x-pack/plugins/lists/server/routes/list/delete_list_route.ts index f2571cd44acf9..d28b777a2ba8e 100644 --- a/x-pack/plugins/lists/server/routes/list/delete_list_route.ts +++ b/x-pack/plugins/lists/server/routes/list/delete_list_route.ts @@ -17,12 +17,13 @@ import { } from '@kbn/securitysolution-io-ts-list-types'; import { getSavedObjectType } from '@kbn/securitysolution-list-utils'; import { LIST_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { DeleteListRequestQuery, DeleteListResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; import type { ExceptionListClient } from '../../services/exception_lists/exception_list_client'; import { escapeQuotes } from '../../services/utils/escape_query'; -import { deleteListRequestQuery, deleteListResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getExceptionListClient, getListClient } from '..'; export const deleteListRoute = (router: ListsPluginRouter): void => { @@ -38,7 +39,7 @@ export const deleteListRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation(deleteListRequestQuery), + query: buildRouteValidationWithZod(DeleteListRequestQuery), }, }, version: '2023-10-31', @@ -49,7 +50,6 @@ export const deleteListRoute = (router: ListsPluginRouter): void => { const lists = await getListClient(context); const exceptionLists = await getExceptionListClient(context); const { id, deleteReferences, ignoreReferences } = request.query; - let deleteExceptionItemResponses; // ignoreReferences=true maintains pre-7.11 behavior of deleting value list without performing any additional checks if (!ignoreReferences) { @@ -75,7 +75,7 @@ export const deleteListRoute = (router: ListsPluginRouter): void => { if (deleteReferences) { // Delete referenced exception list items // TODO: Create deleteListItems to delete in batch - deleteExceptionItemResponses = await Promise.all( + await Promise.all( referencedExceptionListItems.map(async (listItem) => { // Ensure only the single entry is deleted as there could be a separate value list referenced that is okay to keep // TODO: Add API to delete single entry const remainingEntries = listItem.entries.filter( @@ -122,16 +122,9 @@ export const deleteListRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(deleted, deleteListResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ - body: validated ?? { - deleteItemResponses: deleteExceptionItemResponses, - }, - }); - } + return response.ok({ + body: DeleteListResponse.parse(deleted), + }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list/import_list_item_route.ts b/x-pack/plugins/lists/server/routes/list/import_list_item_route.ts index d9d1bc5af1e6e..f3f52828f7872 100644 --- a/x-pack/plugins/lists/server/routes/list/import_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list/import_list_item_route.ts @@ -8,14 +8,17 @@ import { extname } from 'path'; import { schema } from '@kbn/config-schema'; -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + ImportListItemsRequestQuery, + ImportListItemsResponse, +} from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; import { ConfigType } from '../../config'; -import { importListItemRequestQuery, importListItemResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { createStreamFromBuffer } from '../utils/create_stream_from_buffer'; import { getListClient } from '..'; @@ -43,7 +46,7 @@ export const importListItemRoute = (router: ListsPluginRouter, config: ConfigTyp validate: { request: { body: schema.buffer(), - query: buildRouteValidation(importListItemRequestQuery), + query: buildRouteValidationWithZod(ImportListItemsRequestQuery), }, }, version: '2023-10-31', @@ -119,12 +122,7 @@ export const importListItemRoute = (router: ListsPluginRouter, config: ConfigTyp version: 1, }); - const [validated, errors] = validate(list, importListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: ImportListItemsResponse.parse(list) }); } else if (type != null) { const importedList = await lists.importListItemsToStream({ deserializer, @@ -142,12 +140,8 @@ export const importListItemRoute = (router: ListsPluginRouter, config: ConfigTyp statusCode: 400, }); } - const [validated, errors] = validate(importedList, importListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + + return response.ok({ body: ImportListItemsResponse.parse(importedList) }); } else { return siemResponse.error({ body: 'Either type or list_id need to be defined in the query', diff --git a/x-pack/plugins/lists/server/routes/list/patch_list_route.ts b/x-pack/plugins/lists/server/routes/list/patch_list_route.ts index 336239854f70b..fb14166d74f9c 100644 --- a/x-pack/plugins/lists/server/routes/list/patch_list_route.ts +++ b/x-pack/plugins/lists/server/routes/list/patch_list_route.ts @@ -5,13 +5,13 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { PatchListRequestBody, PatchListResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { patchListRequest, patchListResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const patchListRoute = (router: ListsPluginRouter): void => { @@ -27,7 +27,7 @@ export const patchListRoute = (router: ListsPluginRouter): void => { { validate: { request: { - body: buildRouteValidation(patchListRequest), + body: buildRouteValidationWithZod(PatchListRequestBody), }, }, version: '2023-10-31', @@ -54,12 +54,7 @@ export const patchListRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(list, patchListResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: PatchListResponse.parse(list) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list/read_list_route.ts b/x-pack/plugins/lists/server/routes/list/read_list_route.ts index ab403e933e53f..e9af8cfc8f4eb 100644 --- a/x-pack/plugins/lists/server/routes/list/read_list_route.ts +++ b/x-pack/plugins/lists/server/routes/list/read_list_route.ts @@ -5,13 +5,13 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { GetListRequestQuery, GetListResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { readListRequestQuery, readListResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const readListRoute = (router: ListsPluginRouter): void => { @@ -27,7 +27,7 @@ export const readListRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation(readListRequestQuery), + query: buildRouteValidationWithZod(GetListRequestQuery), }, }, version: '2023-10-31', @@ -44,12 +44,7 @@ export const readListRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(list, readListResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: GetListResponse.parse(list) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list/update_list_route.ts b/x-pack/plugins/lists/server/routes/list/update_list_route.ts index 46b2d8e058857..c20714b75e090 100644 --- a/x-pack/plugins/lists/server/routes/list/update_list_route.ts +++ b/x-pack/plugins/lists/server/routes/list/update_list_route.ts @@ -5,13 +5,13 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { UpdateListRequestBody, UpdateListResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { updateListRequest, updateListResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const updateListRoute = (router: ListsPluginRouter): void => { @@ -27,7 +27,7 @@ export const updateListRoute = (router: ListsPluginRouter): void => { { validate: { request: { - body: buildRouteValidation(updateListRequest), + body: buildRouteValidationWithZod(UpdateListRequestBody), }, }, version: '2023-10-31', @@ -54,12 +54,7 @@ export const updateListRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(list, updateListResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: UpdateListResponse.parse(list) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts b/x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts index e3cab179c2f40..2f74871f23fc2 100644 --- a/x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts +++ b/x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts @@ -5,11 +5,10 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_INDEX } from '@kbn/securitysolution-list-constants'; +import { CreateListIndexResponse } from '@kbn/securitysolution-lists-common/api'; -import { createListIndexResponse } from '../../../common/api'; import type { ListsPluginRouter } from '../../types'; import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; @@ -64,12 +63,7 @@ export const createListIndexRoute = (router: ListsPluginRouter): void => { : lists.createListItemDataStream()); } - const [validated, errors] = validate({ acknowledged: true }, createListIndexResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: CreateListIndexResponse.parse({ acknowledged: true }) }); } catch (err) { const error = transformError(err); return siemResponse.error({ diff --git a/x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts b/x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts index a9683f4636151..0814739ab11e7 100644 --- a/x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts +++ b/x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_INDEX } from '@kbn/securitysolution-list-constants'; +import { DeleteListIndexResponse } from '@kbn/securitysolution-lists-common/api'; import { ListClient } from '../../services/lists/list_client'; import type { ListsPluginRouter } from '../../types'; -import { deleteListIndexResponse } from '../../../common/api'; import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; @@ -83,12 +82,7 @@ export const deleteListIndexRoute = (router: ListsPluginRouter): void => { await deleteIndexTemplates(lists); - const [validated, errors] = validate({ acknowledged: true }, deleteListIndexResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: DeleteListIndexResponse.parse({ acknowledged: true }) }); } catch (err) { const error = transformError(err); return siemResponse.error({ diff --git a/x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts index 1d43d4fd8c181..af9c40117f9c6 100644 --- a/x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts @@ -9,10 +9,11 @@ import { Stream } from 'stream'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { ExportListItemsRequestQuery } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { exportListItemRequestQuery } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const exportListItemRoute = (router: ListsPluginRouter): void => { @@ -28,7 +29,7 @@ export const exportListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation(exportListItemRequestQuery), + query: buildRouteValidationWithZod(ExportListItemsRequestQuery), }, }, version: '2023-10-31', diff --git a/x-pack/plugins/lists/server/routes/list_index/find_list_route.ts b/x-pack/plugins/lists/server/routes/list_index/find_list_route.ts index 9b492006e0605..157b11e3832eb 100644 --- a/x-pack/plugins/lists/server/routes/list_index/find_list_route.ts +++ b/x-pack/plugins/lists/server/routes/list_index/find_list_route.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { FindListsRequestQuery, FindListsResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; import { decodeCursor } from '../../services/utils'; -import { findListRequestQuery, findListResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse, getListClient } from '../utils'; +import { buildSiemResponse, getListClient } from '../utils'; export const findListRoute = (router: ListsPluginRouter): void => { router.versioned @@ -27,7 +27,7 @@ export const findListRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation(findListRequestQuery), + query: buildRouteValidationWithZod(FindListsRequestQuery), }, }, version: '2023-10-31', @@ -74,12 +74,8 @@ export const findListRoute = (router: ListsPluginRouter): void => { sortField, sortOrder, }); - const [validated, errors] = validate(exceptionList, findListResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + + return response.ok({ body: FindListsResponse.parse(exceptionList) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts b/x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts index 6e9fdb29e55b8..80637788e00db 100644 --- a/x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts +++ b/x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts @@ -5,12 +5,11 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_INDEX } from '@kbn/securitysolution-list-constants'; +import { GetListIndexResponse } from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { readListIndexResponse } from '../../../common/api'; import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; @@ -37,15 +36,12 @@ export const readListIndexRoute = (router: ListsPluginRouter): void => { const listItemDataStreamExists = await lists.getListItemDataStreamExists(); if (listDataStreamExists && listItemDataStreamExists) { - const [validated, errors] = validate( - { list_index: listDataStreamExists, list_item_index: listItemDataStreamExists }, - readListIndexResponse - ); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ + body: GetListIndexResponse.parse({ + list_index: listDataStreamExists, + list_item_index: listItemDataStreamExists, + }), + }); } else if (!listDataStreamExists && listItemDataStreamExists) { return siemResponse.error({ body: `data stream ${lists.getListName()} does not exist`, diff --git a/x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts index b3ab6f4e09eb7..2f8bd2738ae0f 100644 --- a/x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts @@ -5,13 +5,16 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + CreateListItemRequestBody, + CreateListItemResponse, +} from '@kbn/securitysolution-lists-common/api'; -import { createListItemRequest, createListItemResponse } from '../../../common/api'; import type { ListsPluginRouter } from '../../types'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const createListItemRoute = (router: ListsPluginRouter): void => { @@ -27,7 +30,7 @@ export const createListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - body: buildRouteValidation(createListItemRequest), + body: buildRouteValidationWithZod(CreateListItemRequestBody), }, }, version: '2023-10-31', @@ -63,13 +66,9 @@ export const createListItemRoute = (router: ListsPluginRouter): void => { type: list.type, value, }); + if (createdListItem != null) { - const [validated, errors] = validate(createdListItem, createListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: CreateListItemResponse.parse(createdListItem) }); } else { return siemResponse.error({ body: 'list item invalid', diff --git a/x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts index 644c8235bae06..2cf30a61988b0 100644 --- a/x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts @@ -5,17 +5,16 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + DeleteListItemRequestQuery, + DeleteListItemResponse, +} from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { - deleteListItemArrayResponse, - deleteListItemRequestQuery, - deleteListItemResponse, -} from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const deleteListItemRoute = (router: ListsPluginRouter): void => { @@ -31,7 +30,7 @@ export const deleteListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation(deleteListItemRequestQuery), + query: buildRouteValidationWithZod(DeleteListItemRequestQuery), }, }, version: '2023-10-31', @@ -50,12 +49,7 @@ export const deleteListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(deleted, deleteListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: DeleteListItemResponse.parse(deleted) }); } } else if (listId != null && value != null) { const list = await lists.getList({ id: listId }); @@ -77,12 +71,7 @@ export const deleteListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(deleted, deleteListItemArrayResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: DeleteListItemResponse.parse(deleted) }); } } } else { diff --git a/x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts index 0fd4300ea51dc..f65b678e36242 100644 --- a/x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts @@ -5,18 +5,17 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + FindListItemsRequestQuery, + FindListItemsResponse, +} from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; import { decodeCursor } from '../../services/utils'; -import { - FindListItemRequestQueryDecoded, - findListItemRequestQuery, - findListItemResponse, -} from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse, getListClient } from '../utils'; +import { buildSiemResponse, getListClient } from '../utils'; export const findListItemRoute = (router: ListsPluginRouter): void => { router.versioned @@ -31,10 +30,7 @@ export const findListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation< - typeof findListItemRequestQuery, - FindListItemRequestQueryDecoded - >(findListItemRequestQuery), + query: buildRouteValidationWithZod(FindListItemsRequestQuery), }, }, version: '2023-10-31', @@ -90,12 +86,7 @@ export const findListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(exceptionList, findListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: FindListItemsResponse.parse(exceptionList) }); } } } catch (err) { diff --git a/x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts index ff369aa9403e8..68c82e93fcc38 100644 --- a/x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts @@ -5,13 +5,16 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + PatchListItemRequestBody, + PatchListItemResponse, +} from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { patchListItemRequest, patchListItemResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const patchListItemRoute = (router: ListsPluginRouter): void => { @@ -27,7 +30,7 @@ export const patchListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - body: buildRouteValidation(patchListItemRequest), + body: buildRouteValidationWithZod(PatchListItemRequestBody), }, }, version: '2023-10-31', @@ -61,12 +64,7 @@ export const patchListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(listItem, patchListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: PatchListItemResponse.parse(listItem) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts index 67c4793736483..0e6a9dbe50155 100644 --- a/x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts @@ -5,17 +5,16 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + GetListItemRequestQuery, + GetListItemResponse, +} from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { - readListItemArrayResponse, - readListItemRequestQuery, - readListItemResponse, -} from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const readListItemRoute = (router: ListsPluginRouter): void => { @@ -31,7 +30,7 @@ export const readListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - query: buildRouteValidation(readListItemRequestQuery), + query: buildRouteValidationWithZod(GetListItemRequestQuery), }, }, version: '2023-10-31', @@ -49,12 +48,7 @@ export const readListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(listItem, readListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: GetListItemResponse.parse(listItem) }); } } else if (listId != null && value != null) { const list = await lists.getList({ id: listId }); @@ -75,12 +69,7 @@ export const readListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(listItem, readListItemArrayResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: GetListItemResponse.parse(listItem) }); } } } else { diff --git a/x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts b/x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts index c627f9e9e95ea..8b2c4f65e54eb 100644 --- a/x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts @@ -5,13 +5,16 @@ * 2.0. */ -import { validate } from '@kbn/securitysolution-io-ts-utils'; import { transformError } from '@kbn/securitysolution-es-utils'; import { LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import { + UpdateListItemRequestBody, + UpdateListItemResponse, +} from '@kbn/securitysolution-lists-common/api'; import type { ListsPluginRouter } from '../../types'; -import { updateListItemRequest, updateListItemResponse } from '../../../common/api'; -import { buildRouteValidation, buildSiemResponse } from '../utils'; +import { buildSiemResponse } from '../utils'; import { getListClient } from '..'; export const updateListItemRoute = (router: ListsPluginRouter): void => { @@ -27,7 +30,7 @@ export const updateListItemRoute = (router: ListsPluginRouter): void => { { validate: { request: { - body: buildRouteValidation(updateListItemRequest), + body: buildRouteValidationWithZod(UpdateListItemRequestBody), }, }, version: '2023-10-31', @@ -59,12 +62,7 @@ export const updateListItemRoute = (router: ListsPluginRouter): void => { statusCode: 404, }); } else { - const [validated, errors] = validate(listItem, updateListItemResponse); - if (errors != null) { - return siemResponse.error({ body: errors, statusCode: 500 }); - } else { - return response.ok({ body: validated ?? {} }); - } + return response.ok({ body: UpdateListItemResponse.parse(listItem) }); } } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/lists/tsconfig.json b/x-pack/plugins/lists/tsconfig.json index b18887c254336..47dc15c00ec8b 100644 --- a/x-pack/plugins/lists/tsconfig.json +++ b/x-pack/plugins/lists/tsconfig.json @@ -1,15 +1,14 @@ - { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "outDir": "target/types", + "outDir": "target/types" }, "include": [ "common/**/*", "public/**/*", "server/**/*", // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636 - "server/**/*.json", + "server/**/*.json" ], "kbn_references": [ "@kbn/core", @@ -20,6 +19,7 @@ "@kbn/securitysolution-list-constants", "@kbn/securitysolution-list-hooks", "@kbn/securitysolution-list-api", + "@kbn/securitysolution-lists-common", "@kbn/kibana-react-plugin", "@kbn/i18n", "@kbn/data-plugin", @@ -39,8 +39,7 @@ "@kbn/utility-types", "@kbn/core-elasticsearch-client-server-mocks", "@kbn/core-saved-objects-server", + "@kbn/zod-helpers" ], - "exclude": [ - "target/**/*", - ] + "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts index 51e1843e9b8e8..b6e7ae696b755 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts @@ -6,11 +6,11 @@ */ import { transformError, BadRequestError, getIndexAliases } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { CreateAlertsMigrationRequestBody } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import type { SetupPlugins } from '../../../../plugin'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_URL } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../utils'; import { getTemplateVersion } from '../index/check_template_version'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts index c2e364e58ca5b..f4452c73eaf78 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts @@ -6,11 +6,11 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { AlertsMigrationCleanupRequestBody } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import type { SetupPlugins } from '../../../../plugin'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_URL } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../utils'; import { signalsMigrationService } from '../../migrations/migration_service'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts index bfec0f82867a6..468baae7fdcad 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts @@ -7,11 +7,11 @@ import { transformError, BadRequestError } from '@kbn/securitysolution-es-utils'; import type { RuleDataPluginService } from '@kbn/rule-registry-plugin/server'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { FinalizeAlertsMigrationRequestBody } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import type { SetupPlugins } from '../../../../plugin'; import { DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { isMigrationFailed, isMigrationPending } from '../../migrations/helpers'; import { signalsMigrationService } from '../../migrations/migration_service'; import { buildSiemResponse } from '../utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts index 185e0c6ed6175..418db17b566c5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts @@ -6,10 +6,10 @@ */ import { transformError, getIndexAliases } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { GetAlertsMigrationStatusRequestQuery } from '../../../../../common/api/detection_engine/signals_migration'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_SIGNALS_MIGRATION_STATUS_URL } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { getIndexVersionsByIndex } from '../../migrations/get_index_versions_by_index'; import { getMigrationSavedObjectsByIndex } from '../../migrations/get_migration_saved_objects_by_index'; import { getSignalsIndicesInRange } from '../../migrations/get_signals_indices_in_range'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts index 3030e5fe799b6..5db7cc16b05ec 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts @@ -14,7 +14,7 @@ import { } from '@kbn/rule-data-utils'; import type { ElasticsearchClient, Logger, StartServicesAccessor } from '@kbn/core/server'; import type { AuthenticatedUser } from '@kbn/security-plugin/common'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { SetAlertsStatusRequestBody } from '../../../../../common/api/detection_engine/signals'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts index e868c2b979018..60e0bde69c590 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts @@ -9,8 +9,8 @@ import type { MappingRuntimeFields, Sort } from '@elastic/elasticsearch/lib/api/ import { transformError } from '@kbn/securitysolution-es-utils'; import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { SearchAlertsRequestBody } from '../../../../../common/api/detection_engine/signals'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '../../../../../common/constants'; import { buildSiemResponse } from '../utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_assignees_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_assignees_route.ts index f15342a36f46c..1ce791143705b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_assignees_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_assignees_route.ts @@ -7,6 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { uniq } from 'lodash/fp'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { SetAlertAssigneesRequestBody } from '../../../../../common/api/detection_engine/alert_assignees'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { @@ -14,7 +15,6 @@ import { DETECTION_ENGINE_ALERT_ASSIGNEES_URL, } from '../../../../../common/constants'; import { buildSiemResponse } from '../utils'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { validateAlertAssigneesArrays } from './helpers'; export const setAlertAssigneesRoute = (router: SecuritySolutionPluginRouter) => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts index 95d722ac0a381..c6997cc9a9bed 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts @@ -7,6 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { uniq } from 'lodash/fp'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { ManageAlertTagsRequestBody } from '../../../../../common/api/detection_engine/alert_tags'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { @@ -14,7 +15,6 @@ import { DETECTION_ENGINE_ALERT_TAGS_URL, } from '../../../../../common/constants'; import { buildSiemResponse } from '../utils'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { validateAlertTagsArrays } from './helpers'; export const setAlertTagsRoute = (router: SecuritySolutionPluginRouter) => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts index 76787a82b7799..1b1aeada05660 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts @@ -8,11 +8,11 @@ import type { IKibanaResponse, StartServicesAccessor } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { DETECTION_ENGINE_ALERT_SUGGEST_USERS_URL } from '../../../../../common/constants'; import { buildSiemResponse } from '../utils'; import type { StartPlugins } from '../../../../plugin'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { SuggestUserProfilesRequestQuery } from '../../../../../common/api/detection_engine/users'; export const suggestUserProfilesRoute = ( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts index ff608a6344057..1177d4363fe29 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts @@ -8,6 +8,7 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server'; import { AbortError } from '@kbn/kibana-utils-plugin/common'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { ConfigType } from '../../../../../../config'; import type { PerformBulkActionResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { @@ -22,7 +23,6 @@ import { } from '../../../../../../../common/constants'; import type { SetupPlugins } from '../../../../../../plugin'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { initPromisePool } from '../../../../../../utils/promise_pool'; import { routeLimitedConcurrencyTag } from '../../../../../../utils/route_limited_concurrency_tag'; import { buildMlAuthz } from '../../../../../machine_learning/authz'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index ba6eebce2207c..98910ea337630 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -8,6 +8,7 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { DETECTION_ENGINE_RULES_BULK_CREATE } from '../../../../../../../common/constants'; import { BulkCreateRulesRequestBody, @@ -18,7 +19,6 @@ import { import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { getDuplicates } from './get_duplicates'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { validateRuleDefaultExceptionList } from '../../../logic/exceptions/validate_rule_default_exception_list'; import { validateRulesWithDuplicatedDefaultExceptionsList } from '../../../logic/exceptions/validate_rules_with_duplicated_default_exceptions_list'; import { RULE_MANAGEMENT_BULK_ACTION_SOCKET_TIMEOUT_MS } from '../../timeouts'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts index 234439eb49052..2f1ef59d0971b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts @@ -8,6 +8,7 @@ import type { VersionedRouteConfig } from '@kbn/core-http-server'; import type { IKibanaResponse, Logger, RequestHandler } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { BulkCrudRulesResponse, BulkDeleteRulesRequestBody, @@ -18,7 +19,6 @@ import type { SecuritySolutionPluginRouter, SecuritySolutionRequestHandlerContext, } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse, createBulkErrorObject, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts index a3752d421380b..aa06c04db0619 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts @@ -8,13 +8,12 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../../../../common/constants'; import { BulkPatchRulesRequestBody, BulkCrudRulesResponse, } from '../../../../../../../common/api/detection_engine/rule_management'; - -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { transformBulkError, buildSiemResponse } from '../../../../routes/utils'; import { getIdBulkError } from '../../../utils/utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts index e08d781cd74d8..bae89a74ab0b1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts @@ -6,15 +6,13 @@ */ import type { IKibanaResponse, Logger } from '@kbn/core/server'; - +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { transformError } from '@kbn/securitysolution-es-utils'; import { BulkUpdateRulesRequestBody, validateUpdateRuleProps, BulkCrudRulesResponse, } from '../../../../../../../common/api/detection_engine/rule_management'; - -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { DETECTION_ENGINE_RULES_BULK_UPDATE } from '../../../../../../../common/constants'; import { getIdBulkError } from '../../../utils/utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts index 3819154c1b8a3..aa6425b2e673c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { CreateRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { CreateRuleRequestBody, @@ -14,7 +15,6 @@ import { } from '../../../../../../../common/api/detection_engine/rule_management'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../../../../routes/utils'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { checkDefaultRuleExceptionListReferences } from '../../../logic/exceptions/check_for_default_rule_exception_list'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts index 3cf9aa6a2fb55..42a6a1c47544f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { DeleteRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { DeleteRuleRequestQuery, @@ -14,7 +15,6 @@ import { } from '../../../../../../../common/api/detection_engine/rule_management'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../../../../routes/utils'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { getIdError, transform } from '../../../utils/utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts index 301bb62452f28..478a0ce02cc96 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts @@ -7,14 +7,12 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import type { Logger } from '@kbn/core/server'; - +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import { ExportRulesRequestBody, ExportRulesRequestQuery, } from '../../../../../../../common/api/detection_engine/rule_management'; - -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import type { ConfigType } from '../../../../../../config'; import { getNonPackagedRulesCount } from '../../../logic/search/get_existing_prepackaged_rules'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts index 3cbd164586a9d..02ff637ab6f10 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts @@ -7,7 +7,7 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; - +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { DETECTION_ENGINE_RULES_URL_FIND } from '../../../../../../../common/constants'; import type { FindRulesResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { @@ -18,7 +18,6 @@ import { import type { SecuritySolutionPluginRouter } from '../../../../../../types'; import { findRules } from '../../../logic/search/find_rules'; import { buildSiemResponse } from '../../../../routes/utils'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { transformFindAlerts } from '../../../utils/utils'; export const findRulesRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts index 45379d3d17555..297a4cb587352 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts @@ -11,6 +11,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { createPromiseFromStreams } from '@kbn/utils'; import { chunk } from 'lodash/fp'; import { extname } from 'path'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { ImportRulesRequestQuery, ImportRulesResponse, @@ -18,7 +19,6 @@ import { import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import type { ConfigType } from '../../../../../../config'; import type { HapiReadableStream, SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import type { BulkError, ImportRuleResponse } from '../../../../routes/utils'; import { buildSiemResponse, isBulkError, isImportRegular } from '../../../../routes/utils'; import { importRuleActionConnectors } from '../../../logic/import/action_connectors/import_rule_action_connectors'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts index 38b283b2c5fb6..506b36d4441dc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { PatchRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { PatchRuleRequestBody, @@ -14,7 +15,6 @@ import { } from '../../../../../../../common/api/detection_engine/rule_management'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../../../../routes/utils'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { checkDefaultRuleExceptionListReferences } from '../../../logic/exceptions/check_for_default_rule_exception_list'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts index 95992618b0625..a119d1afae912 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { ReadRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { ReadRuleRequestQuery, @@ -14,7 +15,6 @@ import { } from '../../../../../../../common/api/detection_engine/rule_management'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../../../../routes/utils'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { getIdError, transform } from '../../../utils/utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts index 5ac2df600908c..5e77fa64e1fb9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { UpdateRuleResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { UpdateRuleRequestBody, @@ -14,7 +15,6 @@ import { } from '../../../../../../../common/api/detection_engine/rule_management'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../../../common/constants'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../../../../routes/utils'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { checkDefaultRuleExceptionListReferences } from '../../../logic/exceptions/check_for_default_rule_exception_list'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.ts index 4a01a6550cabc..4e8001193b5c5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.ts @@ -7,7 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import type { IKibanaResponse } from '@kbn/core/server'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { buildSiemResponse } from '../../../../routes/utils'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.ts index 6c71652d27e34..bf3a9864260ac 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.ts @@ -7,8 +7,8 @@ import type { IKibanaResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { SecuritySolutionPluginRouter } from '../../../../../../types'; -import { buildRouteValidationWithZod } from '../../../../../../utils/build_validation/route_validation'; import { buildSiemResponse } from '../../../../routes/utils'; import type { GetRuleExecutionResultsResponse } from '../../../../../../../common/api/detection_engine/rule_monitoring'; 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 8c4137bf3d386..c2faa464b75da 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 @@ -19,7 +19,7 @@ import type { import { parseDuration, DISABLE_FLAPPING_SETTINGS } from '@kbn/alerting-plugin/common'; import type { ExecutorType } from '@kbn/alerting-plugin/server/types'; import type { Alert } from '@kbn/alerting-plugin/server'; - +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { DEFAULT_PREVIEW_INDEX, DETECTION_ENGINE_RULES_PREVIEW, @@ -40,7 +40,6 @@ import { createPreviewRuleExecutionLogger } from './preview_rule_execution_logge import { parseInterval } from '../../../rule_types/utils/utils'; import { buildMlAuthz } from '../../../../machine_learning/authz'; import { throwAuthzError } from '../../../../machine_learning/validation'; -import { buildRouteValidationWithZod } from '../../../../../utils/build_validation/route_validation'; import { routeLimitedConcurrencyTag } from '../../../../../utils/route_limited_concurrency_tag'; import type { SecuritySolutionPluginRouter } from '../../../../../types'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts index e2737c6ebe045..c7a0f07400cc8 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { SecuritySolutionRequestHandlerContext } from '../../../../types'; import { ASSET_CRITICALITY_PUBLIC_URL, @@ -16,7 +17,6 @@ import { API_VERSIONS, } from '../../../../../common/constants'; import { DeleteAssetCriticalityRecord } from '../../../../../common/api/entity_analytics/asset_criticality'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled'; import type { EntityAnalyticsRoutesDeps } from '../../types'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts index 57e52724b94ce..07d0cb3098dbc 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { SecuritySolutionRequestHandlerContext } from '../../../../types'; import { ASSET_CRITICALITY_INTERNAL_URL, @@ -16,7 +17,6 @@ import { API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { AssetCriticalityRecordIdParts } from '../../../../../common/api/entity_analytics/asset_criticality'; import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled'; import type { EntityAnalyticsRoutesDeps } from '../../types'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts index d367a1f8bd4d3..78fbe29786298 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts @@ -7,6 +7,7 @@ import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { SecuritySolutionRequestHandlerContext } from '../../../../types'; import { ASSET_CRITICALITY_PUBLIC_URL, @@ -16,7 +17,6 @@ import { API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { CreateAssetCriticalityRecord } from '../../../../../common/api/entity_analytics'; import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts index be4875d7dee04..1602e724db227 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts @@ -8,13 +8,13 @@ import type { Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { RiskScoresCalculationRequest } from '../../../../../common/api/entity_analytics/risk_engine/calculation_route.gen'; import { APP_ID, DEFAULT_RISK_SCORE_PAGE_SIZE, RISK_SCORE_CALCULATION_URL, } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { getRiskInputsIndex } from '../get_risk_inputs_index'; import type { EntityAnalyticsRoutesDeps } from '../../types'; import { RiskScoreAuditActions } from '../audit'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/entity_calculation.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/entity_calculation.ts index fe6e404e9e96d..eeb773b41a180 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/entity_calculation.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/entity_calculation.ts @@ -5,16 +5,15 @@ * 2.0. */ +import { isEmpty } from 'lodash/fp'; import type { Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; - -import { isEmpty } from 'lodash/fp'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import type { RiskScoresCalculationResponse } from '../../../../../common/api/entity_analytics/risk_engine/calculation_route.gen'; import type { AfterKeys } from '../../../../../common/api/entity_analytics/common'; import { RiskScoresEntityCalculationRequest } from '../../../../../common/api/entity_analytics/risk_engine/entity_calculation_route.gen'; import { APP_ID, RISK_SCORE_ENTITY_CALCULATION_URL } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { getRiskInputsIndex } from '../get_risk_inputs_index'; import type { EntityAnalyticsRoutesDeps } from '../../types'; import { RiskScoreAuditActions } from '../audit'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts index 0979b5900737a..d17dc8c99e19e 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts @@ -8,14 +8,13 @@ import type { Logger } from '@kbn/core/server'; import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; import { transformError } from '@kbn/securitysolution-es-utils'; - +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; import { RiskScoresPreviewRequest } from '../../../../../common/api/entity_analytics/risk_engine/preview_route.gen'; import { APP_ID, DEFAULT_RISK_SCORE_PAGE_SIZE, RISK_SCORE_PREVIEW_URL, } from '../../../../../common/constants'; -import { buildRouteValidationWithZod } from '../../../../utils/build_validation/route_validation'; import { getRiskInputsIndex } from '../get_risk_inputs_index'; import type { EntityAnalyticsRoutesDeps } from '../../types'; import { RiskScoreAuditActions } from '../audit'; diff --git a/x-pack/plugins/security_solution/server/utils/build_validation/route_validation.ts b/x-pack/plugins/security_solution/server/utils/build_validation/route_validation.ts index 7775186cde97f..57692b515a230 100644 --- a/x-pack/plugins/security_solution/server/utils/build_validation/route_validation.ts +++ b/x-pack/plugins/security_solution/server/utils/build_validation/route_validation.ts @@ -14,8 +14,6 @@ import type { RouteValidationResultFactory, RouteValidationError, } from '@kbn/core/server'; -import type { TypeOf, ZodType } from 'zod'; -import { stringifyZodError } from '@kbn/zod-helpers'; import type { GenericIntersectionC } from '../runtime_types'; import { excess } from '../runtime_types'; @@ -67,14 +65,3 @@ export const buildRouteValidationWithExcess = (validatedInput: A) => validationResult.ok(validatedInput) ) ); - -export const buildRouteValidationWithZod = - >(schema: T): RouteValidationFunction => - (inputValue: unknown, validationResult: RouteValidationResultFactory) => { - const decoded = schema.safeParse(inputValue); - if (decoded.success) { - return validationResult.ok(decoded.data); - } else { - return validationResult.badRequest(stringifyZodError(decoded.error)); - } - }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/find_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/find_list_items.ts index 0c8aa8aa50fa8..aed7d61acf7b2 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/find_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/find_list_items.ts @@ -5,27 +5,20 @@ * 2.0. */ -import expect from '@kbn/expect'; +import expect from 'expect'; import { LIST_URL, LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; import { LIST_ITEM_ID, LIST_ID } from '@kbn/lists-plugin/common/constants.mock'; -import { getListItemResponseMockWithoutAutoGeneratedValues } from '@kbn/lists-plugin/common/schemas/response/list_item_schema.mock'; import { getCreateMinimalListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_list_item_schema.mock'; import { getCreateMinimalListSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_list_schema.mock'; -import { - createListsIndex, - deleteListsIndex, - removeListItemServerGeneratedProperties, -} from '../../../utils'; +import { createListsIndex, deleteListsIndex } from '../../../utils'; import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); describe('@ess @serverless find_list_items', () => { describe('find list items', () => { @@ -44,9 +37,9 @@ export default ({ getService }: FtrProviderContext): void => { .send() .expect(400); - expect(body).to.eql({ + expect(body).toEqual({ error: 'Bad Request', - message: '[request query]: Invalid value "undefined" supplied to "list_id"', + message: '[request query]: list_id: Required', statusCode: 400, }); }); @@ -58,8 +51,8 @@ export default ({ getService }: FtrProviderContext): void => { .send() .expect(404); - expect(body).to.eql({ - message: 'list id: "some-list-item-id" does not exist', + expect(body).toEqual({ + message: expect.any(String), status_code: 404, }); }); @@ -77,7 +70,7 @@ export default ({ getService }: FtrProviderContext): void => { .send() .expect(200); - expect(body).to.eql({ + expect(body).toEqual({ cursor: 'WzBd', data: [], page: 1, @@ -87,17 +80,12 @@ export default ({ getService }: FtrProviderContext): void => { }); it('should return a single list item when a single list item is loaded from a find with defaults added', async () => { - await supertest - .post(LIST_URL) - .set('kbn-xsrf', 'true') - .send(getCreateMinimalListSchemaMock()) - .expect(200); + const listMock = getCreateMinimalListSchemaMock(); + const listItemMock = getCreateMinimalListItemSchemaMock(); - await supertest - .post(LIST_ITEM_URL) - .set('kbn-xsrf', 'true') - .send(getCreateMinimalListItemSchemaMock()) - .expect(200); + await supertest.post(LIST_URL).set('kbn-xsrf', 'true').send(listMock).expect(200); + + await supertest.post(LIST_ITEM_URL).set('kbn-xsrf', 'true').send(listItemMock).expect(200); const { body } = await supertest .get(`${LIST_ITEM_URL}/_find?list_id=${LIST_ID}`) @@ -105,11 +93,14 @@ export default ({ getService }: FtrProviderContext): void => { .send() .expect(200); - body.data = [removeListItemServerGeneratedProperties(body.data[0])]; - // cursor is a constant changing value so we have to delete it as well. - delete body.cursor; - expect(body).to.eql({ - data: [getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME)], + expect(body).toMatchObject({ + data: [ + expect.objectContaining({ + list_id: listItemMock.list_id, + value: listItemMock.value, + type: listMock.type, + }), + ], page: 1, per_page: 20, total: 1, diff --git a/yarn.lock b/yarn.lock index a5738570ec387..64ba753c57695 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5680,6 +5680,10 @@ version "0.0.0" uid "" +"@kbn/openapi-common@link:packages/kbn-openapi-common": + version "0.0.0" + uid "" + "@kbn/openapi-generator@link:packages/kbn-openapi-generator": version "0.0.0" uid "" @@ -6200,6 +6204,10 @@ version "0.0.0" uid "" +"@kbn/securitysolution-lists-common@link:packages/kbn-securitysolution-lists-common": + version "0.0.0" + uid "" + "@kbn/securitysolution-rules@link:packages/kbn-securitysolution-rules": version "0.0.0" uid "" From 858ef15c5a0dac61d0a4229a48ed8aad9a4a7f04 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Tue, 18 Jun 2024 22:29:29 +0200 Subject: [PATCH 081/127] [Security Solution] Auto-bundle Detections API OpenAPI specs (#186384) **Addresses:** https://github.com/elastic/kibana/issues/184428 ## Summary This PR adds scripts for automatic bundling Detections API OpenAPI spec as a part of PR pipeline. Corresponding resulting bundles are automatically committed to `x-pack/plugins/security_solution/docs/openapi/ess/` and `x-pack/plugins/security_solution/docs/openapi/serverless` folders. --- .../security_solution_openapi_bundling.sh | 10 + .../set_alert_assignees_route.schema.yaml | 3 +- ...les_and_timelines_status_route.schema.yaml | 3 +- ...uilt_rules_and_timelines_route.schema.yaml | 3 +- .../bulk_actions_route.schema.yaml | 3 +- .../bulk_create_rules_route.schema.yaml | 2 +- .../bulk_delete_rules_route.schema.yaml | 3 +- .../bulk_patch_rules_route.schema.yaml | 3 +- .../bulk_update_rules_route.schema.yaml | 3 +- .../create_rule/create_rule_route.schema.yaml | 2 +- .../delete_rule/delete_rule_route.schema.yaml | 3 +- .../patch_rule/patch_rule_route.schema.yaml | 3 +- .../read_rule/read_rule_route.schema.yaml | 3 +- .../update_rule/update_rule_route.schema.yaml | 3 +- .../export_rules_route.schema.yaml | 3 +- .../find_rules/find_rules_route.schema.yaml | 3 +- .../import_rules_route.schema.yaml | 3 +- .../read_tags/read_tags_route.schema.yaml | 3 +- ...et_rule_execution_events_route.schema.yaml | 4 +- ...t_rule_execution_results_route.schema.yaml | 4 +- .../suggest_user_profiles_route.schema.yaml | 4 +- ...ections_api_2023_10_31.bundled.schema.yaml | 5682 +++++++++++++++++ ...ections_api_2023_10_31.bundled.schema.yaml | 5485 ++++++++++++++++ .../scripts/openapi/bundle.js | 24 +- .../scripts/openapi/generate.js | 4 +- 25 files changed, 11237 insertions(+), 29 deletions(-) create mode 100644 .buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh create mode 100644 x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml create mode 100644 x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml diff --git a/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh b/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh new file mode 100644 index 0000000000000..be17669d980b6 --- /dev/null +++ b/.buildkite/scripts/steps/openapi_bundling/security_solution_openapi_bundling.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +echo --- Security Solution OpenAPI Bundling + +(cd x-pack/plugins/security_solution && yarn openapi:bundle) +check_for_changed_files "yarn openapi:bundle" true diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/alert_assignees/set_alert_assignees_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/alert_assignees/set_alert_assignees_route.schema.yaml index 77fd51fe99494..739386d637abd 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/alert_assignees/set_alert_assignees_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/alert_assignees/set_alert_assignees_route.schema.yaml @@ -6,8 +6,9 @@ paths: /api/detection_engine/signals/assignees: summary: Assigns users to alerts post: - operationId: SetAlertAssignees + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: SetAlertAssignees description: Assigns users to alerts. requestBody: required: true diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.schema.yaml index 3a7a19611a144..92b82e9d1e849 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/prepackaged/_status: get: - operationId: GetPrebuiltRulesAndTimelinesStatus + x-labels: [ess] x-codegen-enabled: true + operationId: GetPrebuiltRulesAndTimelinesStatus summary: Get the status of Elastic prebuilt rules tags: - Prebuilt Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.schema.yaml index 3aeb1b04317f9..ab27c71c4ef33 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/prepackaged: put: - operationId: InstallPrebuiltRulesAndTimelines + x-labels: [ess] x-codegen-enabled: true + operationId: InstallPrebuiltRulesAndTimelines summary: Installs all Elastic prebuilt rules and timelines tags: - Prebuilt Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.schema.yaml index 6b5a3aa1c6982..a2e75b8ae4fb6 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/_bulk_action: post: - operationId: PerformBulkAction + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: PerformBulkAction summary: Applies a bulk action to multiple rules description: The bulk action is applied to all rules that match the filter or to the list of rules by their IDs. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_create_rules/bulk_create_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_create_rules/bulk_create_rules_route.schema.yaml index 002fa5613eed9..127ad9784988d 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_create_rules/bulk_create_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_create_rules/bulk_create_rules_route.schema.yaml @@ -6,8 +6,8 @@ paths: /api/detection_engine/rules/_bulk_create: post: x-labels: [ess] - operationId: BulkCreateRules x-codegen-enabled: true + operationId: BulkCreateRules deprecated: true description: Creates new detection rules in bulk. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_delete_rules/bulk_delete_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_delete_rules/bulk_delete_rules_route.schema.yaml index 8438bb5b60052..02f78a65fee7c 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_delete_rules/bulk_delete_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_delete_rules/bulk_delete_rules_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/_bulk_delete: delete: - operationId: BulkDeleteRules + x-labels: [ess] x-codegen-enabled: true + operationId: BulkDeleteRules deprecated: true description: Deletes multiple rules. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_patch_rules/bulk_patch_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_patch_rules/bulk_patch_rules_route.schema.yaml index 7ba82e4ad3673..65bd0e1a4ac36 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_patch_rules/bulk_patch_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_patch_rules/bulk_patch_rules_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/_bulk_update: patch: - operationId: BulkPatchRules + x-labels: [ess] x-codegen-enabled: true + operationId: BulkPatchRules deprecated: true description: Updates multiple rules using the `PATCH` method. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_update_rules/bulk_update_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_update_rules/bulk_update_rules_route.schema.yaml index 6f85e51c6a01e..37241035439d3 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_update_rules/bulk_update_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/bulk_crud/bulk_update_rules/bulk_update_rules_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/_bulk_update: put: - operationId: BulkUpdateRules + x-labels: [ess] x-codegen-enabled: true + operationId: BulkUpdateRules deprecated: true description: Updates multiple rules using the `PUT` method. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/create_rule/create_rule_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/create_rule/create_rule_route.schema.yaml index 464a2df0641e3..a5071837af2cf 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/create_rule/create_rule_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/create_rule/create_rule_route.schema.yaml @@ -6,8 +6,8 @@ paths: /api/detection_engine/rules: post: x-labels: [ess, serverless] - operationId: CreateRule x-codegen-enabled: true + operationId: CreateRule description: Create a single detection rule tags: - Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/delete_rule/delete_rule_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/delete_rule/delete_rule_route.schema.yaml index be55d0add8322..b6ef8a444eb55 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/delete_rule/delete_rule_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/delete_rule/delete_rule_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules: delete: - operationId: DeleteRule + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: DeleteRule description: Deletes a single rule using the `rule_id` or `id` field. tags: - Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.schema.yaml index df2bdb114c2e0..aec02102bcca4 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules: patch: - operationId: PatchRule + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: PatchRule description: Patch a single rule tags: - Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.schema.yaml index bcb4cc83381df..817579eb8c27e 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules: get: - operationId: ReadRule + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: ReadRule description: Read a single rule tags: - Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/update_rule/update_rule_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/update_rule/update_rule_route.schema.yaml index e32a3cd52e688..de82265ca3379 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/update_rule/update_rule_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/crud/update_rule/update_rule_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules: put: - operationId: UpdateRule + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: UpdateRule description: Update a single rule tags: - Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/export_rules/export_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/export_rules/export_rules_route.schema.yaml index 73c60f76e19a8..0a88075abb158 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/export_rules/export_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/export_rules/export_rules_route.schema.yaml @@ -6,8 +6,9 @@ paths: /api/detection_engine/rules/_export: summary: Exports rules to an `.ndjson` file post: - operationId: ExportRules + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: ExportRules summary: Export rules description: Exports rules to an `.ndjson` file. The following configuration items are also included in the `.ndjson` file - Actions, Exception lists. Prebuilt rules cannot be exported. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/find_rules/find_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/find_rules/find_rules_route.schema.yaml index 4a37d1f9f5bc9..4f27662e37bfd 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/find_rules/find_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/find_rules/find_rules_route.schema.yaml @@ -5,8 +5,9 @@ info: paths: /api/detection_engine/rules/_find: get: - operationId: FindRules + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: FindRules description: Finds rules that match the given query. tags: - Rules API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/import_rules_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/import_rules_route.schema.yaml index ddc0f063747ec..9056fcea04bca 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/import_rules_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/import_rules_route.schema.yaml @@ -6,8 +6,9 @@ paths: /api/detection_engine/rules/_import: summary: Imports rules from an `.ndjson` file post: - operationId: ImportRules + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: ImportRules summary: Import rules description: Imports rules from an `.ndjson` file, including actions and exception lists. tags: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/read_tags/read_tags_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/read_tags/read_tags_route.schema.yaml index ae4ef41a9ff32..0a9d622dd2d4a 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/read_tags/read_tags_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/read_tags/read_tags_route.schema.yaml @@ -6,8 +6,9 @@ paths: /api/detection_engine/tags: summary: Aggregates and returns rule tags get: - operationId: ReadTags + x-labels: [ess, serverless] x-codegen-enabled: true + operationId: ReadTags summary: Aggregates and returns all unique tags from all rules tags: - Tags API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.schema.yaml index 990ea4ef64876..c1f9a7cdd5096 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.schema.yaml @@ -5,8 +5,10 @@ info: paths: /internal/detection_engine/rules/{ruleId}/execution/events: put: - operationId: GetRuleExecutionEvents + x-labels: [ess, serverless] + x-internal: true x-codegen-enabled: true + operationId: GetRuleExecutionEvents summary: Returns execution events of a given rule (aggregated by execution UUID) from Event Log. tags: - Rule Execution Log API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.schema.yaml index 42f8d54a2e616..a9a4eb2aca7e1 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.schema.yaml @@ -5,8 +5,10 @@ info: paths: /internal/detection_engine/rules/{ruleId}/execution/results: put: - operationId: GetRuleExecutionResults + x-labels: [ess, serverless] + x-internal: true x-codegen-enabled: true + operationId: GetRuleExecutionResults summary: Returns execution results of a given rule (aggregated by execution UUID) from Event Log. tags: - Rule Execution Log API diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/users/suggest_user_profiles_route.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/users/suggest_user_profiles_route.schema.yaml index a4778969d0312..e4254bee52a37 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/users/suggest_user_profiles_route.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/users/suggest_user_profiles_route.schema.yaml @@ -6,8 +6,10 @@ paths: /internal/detection_engine/users/_find: summary: Suggests user profiles based on provided search term post: - operationId: SuggestUserProfiles + x-labels: [ess, serverless] + x-internal: true x-codegen-enabled: true + operationId: SuggestUserProfiles description: Suggests user profiles. parameters: - name: searchTerm diff --git a/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml b/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml new file mode 100644 index 0000000000000..ca8bae8f42f0f --- /dev/null +++ b/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml @@ -0,0 +1,5682 @@ +openapi: 3.0.3 +info: + description: >- + You can create rules that automatically turn events and external alerts sent + to Elastic Security into detection alerts. These alerts are displayed on the + Detections page. + title: Security Solution Detections API (Elastic Cloud and self-hosted) + version: '2023-10-31' +servers: + - url: 'http://{kibana_host}:{port}' + variables: + kibana_host: + default: localhost + port: + default: '5601' +paths: + /api/detection_engine/rules: + delete: + description: Deletes a single rule using the `rule_id` or `id` field. + operationId: DeleteRule + parameters: + - description: The rule's `id` value. + in: query + name: id + required: false + schema: + $ref: '#/components/schemas/RuleObjectId' + - description: The rule's `rule_id` value. + in: query + name: rule_id + required: false + schema: + $ref: '#/components/schemas/RuleSignatureId' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + get: + description: Read a single rule + operationId: ReadRule + parameters: + - description: The rule's `id` value. + in: query + name: id + required: false + schema: + $ref: '#/components/schemas/RuleObjectId' + - description: The rule's `rule_id` value. + in: query + name: rule_id + required: false + schema: + $ref: '#/components/schemas/RuleSignatureId' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + patch: + description: Patch a single rule + operationId: PatchRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RulePatchProps' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + post: + description: Create a single detection rule + operationId: CreateRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RuleCreateProps' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + put: + description: Update a single rule + operationId: UpdateRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RuleUpdateProps' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + /api/detection_engine/rules/_bulk_action: + post: + description: >- + The bulk action is applied to all rules that match the filter or to the + list of rules by their IDs. + operationId: PerformBulkAction + parameters: + - description: Enables dry run mode for the request call. + in: query + name: dry_run + required: false + schema: + type: boolean + requestBody: + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/BulkDeleteRules' + - $ref: '#/components/schemas/BulkDisableRules' + - $ref: '#/components/schemas/BulkEnableRules' + - $ref: '#/components/schemas/BulkExportRules' + - $ref: '#/components/schemas/BulkDuplicateRules' + - $ref: '#/components/schemas/BulkEditRules' + responses: + '200': + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/BulkEditActionResponse' + - $ref: '#/components/schemas/BulkExportActionResponse' + description: OK + summary: Applies a bulk action to multiple rules + tags: + - Bulk API + /api/detection_engine/rules/_bulk_create: + post: + deprecated: true + description: Creates new detection rules in bulk. + operationId: BulkCreateRules + requestBody: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/RuleCreateProps' + type: array + description: 'A JSON array of rules, where each rule contains the required fields.' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/BulkCrudRulesResponse' + description: Indicates a successful call. + tags: + - Bulk API + /api/detection_engine/rules/_bulk_delete: + delete: + deprecated: true + description: Deletes multiple rules. + operationId: BulkDeleteRules + requestBody: + content: + application/json: + schema: + items: + type: object + properties: + id: + $ref: '#/components/schemas/RuleObjectId' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + type: array + description: >- + A JSON array of `id` or `rule_id` fields of the rules you want to + delete. + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/BulkCrudRulesResponse' + description: Indicates a successful call. + tags: + - Bulk API + /api/detection_engine/rules/_bulk_update: + patch: + deprecated: true + description: Updates multiple rules using the `PATCH` method. + operationId: BulkPatchRules + requestBody: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/RulePatchProps' + type: array + description: 'A JSON array of rules, where each rule contains the required fields.' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/BulkCrudRulesResponse' + description: Indicates a successful call. + tags: + - Bulk API + put: + deprecated: true + description: Updates multiple rules using the `PUT` method. + operationId: BulkUpdateRules + requestBody: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/RuleUpdateProps' + type: array + description: >- + A JSON array where each element includes the `id` or `rule_id` field + of the rule you want to update and the fields you want to modify. + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/BulkCrudRulesResponse' + description: Indicates a successful call. + tags: + - Bulk API + /api/detection_engine/rules/_export: + post: + description: >- + Exports rules to an `.ndjson` file. The following configuration items + are also included in the `.ndjson` file - Actions, Exception lists. + Prebuilt rules cannot be exported. + operationId: ExportRules + parameters: + - description: Determines whether a summary of the exported rules is returned. + in: query + name: exclude_export_details + required: false + schema: + default: false + type: boolean + - description: File name for saving the exported rules. + in: query + name: file_name + required: false + schema: + default: export.ndjson + type: string + requestBody: + content: + application/json: + schema: + nullable: true + type: object + properties: + objects: + description: >- + Array of `rule_id` fields. Exports all rules when + unspecified. + items: + type: object + properties: + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + required: + - rule_id + type: array + required: + - objects + required: false + responses: + '200': + content: + application/ndjson: + schema: + description: An `.ndjson` file containing the returned rules. + format: binary + type: string + description: Indicates a successful call. + summary: Export rules + tags: + - Import/Export API + summary: Exports rules to an `.ndjson` file + /api/detection_engine/rules/_find: + get: + description: Finds rules that match the given query. + operationId: FindRules + parameters: + - in: query + name: fields + required: false + schema: + items: + type: string + type: array + - description: Search query + in: query + name: filter + required: false + schema: + type: string + - description: Field to sort by + in: query + name: sort_field + required: false + schema: + $ref: '#/components/schemas/FindRulesSortField' + - description: Sort order + in: query + name: sort_order + required: false + schema: + $ref: '#/components/schemas/SortOrder' + - description: Page number + in: query + name: page + required: false + schema: + default: 1 + minimum: 1 + type: integer + - description: Rules per page + in: query + name: per_page + required: false + schema: + default: 20 + minimum: 0 + type: integer + responses: + '200': + content: + application/json: + schema: + type: object + properties: + data: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + page: + type: integer + perPage: + type: integer + total: + type: integer + required: + - page + - perPage + - total + - data + description: Successful response + tags: + - Rules API + /api/detection_engine/rules/_import: + post: + description: >- + Imports rules from an `.ndjson` file, including actions and exception + lists. + operationId: ImportRules + parameters: + - description: >- + Determines whether existing rules with the same `rule_id` are + overwritten. + in: query + name: overwrite + required: false + schema: + default: false + type: boolean + - description: >- + Determines whether existing exception lists with the same `list_id` + are overwritten. + in: query + name: overwrite_exceptions + required: false + schema: + default: false + type: boolean + - description: >- + Determines whether existing actions with the same + `kibana.alert.rule.actions.id` are overwritten. + in: query + name: overwrite_action_connectors + required: false + schema: + default: false + type: boolean + - description: Generates a new list ID for each imported exception list. + in: query + name: as_new_list + required: false + schema: + default: false + type: boolean + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + description: The `.ndjson` file containing the rules. + format: binary + type: string + required: true + responses: + '200': + content: + application/json: + schema: + additionalProperties: false + type: object + properties: + action_connectors_errors: + items: + $ref: '#/components/schemas/ErrorSchema' + type: array + action_connectors_success: + type: boolean + action_connectors_success_count: + minimum: 0 + type: integer + action_connectors_warnings: + items: + $ref: '#/components/schemas/WarningSchema' + type: array + errors: + items: + $ref: '#/components/schemas/ErrorSchema' + type: array + exceptions_errors: + items: + $ref: '#/components/schemas/ErrorSchema' + type: array + exceptions_success: + type: boolean + exceptions_success_count: + minimum: 0 + type: integer + rules_count: + minimum: 0 + type: integer + success: + type: boolean + success_count: + minimum: 0 + type: integer + required: + - exceptions_success + - exceptions_success_count + - exceptions_errors + - rules_count + - success + - success_count + - errors + - action_connectors_errors + - action_connectors_warnings + - action_connectors_success + - action_connectors_success_count + description: Indicates a successful call. + summary: Import rules + tags: + - Import/Export API + summary: Imports rules from an `.ndjson` file + /api/detection_engine/rules/prepackaged: + put: + operationId: InstallPrebuiltRulesAndTimelines + responses: + '200': + content: + application/json: + schema: + additionalProperties: false + type: object + properties: + rules_installed: + description: The number of rules installed + minimum: 0 + type: integer + rules_updated: + description: The number of rules updated + minimum: 0 + type: integer + timelines_installed: + description: The number of timelines installed + minimum: 0 + type: integer + timelines_updated: + description: The number of timelines updated + minimum: 0 + type: integer + required: + - rules_installed + - rules_updated + - timelines_installed + - timelines_updated + description: Indicates a successful call + summary: Installs all Elastic prebuilt rules and timelines + tags: + - Prebuilt Rules API + /api/detection_engine/rules/prepackaged/_status: + get: + operationId: GetPrebuiltRulesAndTimelinesStatus + responses: + '200': + content: + application/json: + schema: + additionalProperties: false + type: object + properties: + rules_custom_installed: + description: The total number of custom rules + minimum: 0 + type: integer + rules_installed: + description: The total number of installed prebuilt rules + minimum: 0 + type: integer + rules_not_installed: + description: >- + The total number of available prebuilt rules that are not + installed + minimum: 0 + type: integer + rules_not_updated: + description: The total number of outdated prebuilt rules + minimum: 0 + type: integer + timelines_installed: + description: The total number of installed prebuilt timelines + minimum: 0 + type: integer + timelines_not_installed: + description: >- + The total number of available prebuilt timelines that are + not installed + minimum: 0 + type: integer + timelines_not_updated: + description: The total number of outdated prebuilt timelines + minimum: 0 + type: integer + required: + - rules_custom_installed + - rules_installed + - rules_not_installed + - rules_not_updated + - timelines_installed + - timelines_not_installed + - timelines_not_updated + description: Indicates a successful call + summary: Get the status of Elastic prebuilt rules + tags: + - Prebuilt Rules API + /api/detection_engine/signals/assignees: + post: + description: Assigns users to alerts. + operationId: SetAlertAssignees + requestBody: + content: + application/json: + schema: + type: object + properties: + assignees: + $ref: '#/components/schemas/AlertAssignees' + description: Details about the assignees to assign and unassign. + ids: + $ref: '#/components/schemas/AlertIds' + description: List of alerts ids to assign and unassign passed assignees. + required: + - assignees + - ids + required: true + responses: + '200': + description: Indicates a successful call. + '400': + description: Invalid request. + summary: Assigns users to alerts + /api/detection_engine/tags: + get: + operationId: ReadTags + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleTagArray' + description: Indicates a successful call + summary: Aggregates and returns all unique tags from all rules + tags: + - Tags API + summary: Aggregates and returns rule tags +components: + schemas: + AlertAssignees: + type: object + properties: + add: + description: A list of users ids to assign. + items: + $ref: '#/components/schemas/NonEmptyString' + type: array + remove: + description: A list of users ids to unassign. + items: + $ref: '#/components/schemas/NonEmptyString' + type: array + required: + - add + - remove + AlertIds: + description: A list of alerts ids. + items: + $ref: '#/components/schemas/NonEmptyString' + minItems: 1 + type: array + AlertsIndex: + deprecated: true + description: (deprecated) Has no effect. + type: string + AlertsIndexNamespace: + description: Has no effect. + type: string + AlertSuppression: + type: object + properties: + duration: + $ref: '#/components/schemas/AlertSuppressionDuration' + group_by: + $ref: '#/components/schemas/AlertSuppressionGroupBy' + missing_fields_strategy: + $ref: '#/components/schemas/AlertSuppressionMissingFieldsStrategy' + required: + - group_by + AlertSuppressionDuration: + type: object + properties: + unit: + enum: + - s + - m + - h + type: string + value: + minimum: 1 + type: integer + required: + - value + - unit + AlertSuppressionGroupBy: + items: + type: string + maxItems: 3 + minItems: 1 + type: array + AlertSuppressionMissingFieldsStrategy: + description: >- + Describes how alerts will be generated for documents with missing + suppress by fields: + + doNotSuppress - per each document a separate alert will be created + + suppress - only alert will be created per suppress by bucket + enum: + - doNotSuppress + - suppress + type: string + AnomalyThreshold: + description: Anomaly threshold + minimum: 0 + type: integer + BuildingBlockType: + description: >- + Determines if the rule acts as a building block. By default, + building-block alerts are not displayed in the UI. These rules are used + as a foundation for other rules that do generate alerts. Its value must + be default. + type: string + BulkActionEditPayload: + anyOf: + - $ref: '#/components/schemas/BulkActionEditPayloadTags' + - $ref: '#/components/schemas/BulkActionEditPayloadIndexPatterns' + - $ref: '#/components/schemas/BulkActionEditPayloadInvestigationFields' + - $ref: '#/components/schemas/BulkActionEditPayloadTimeline' + - $ref: '#/components/schemas/BulkActionEditPayloadRuleActions' + - $ref: '#/components/schemas/BulkActionEditPayloadSchedule' + BulkActionEditPayloadIndexPatterns: + type: object + properties: + overwrite_data_views: + type: boolean + type: + enum: + - add_index_patterns + - delete_index_patterns + - set_index_patterns + type: string + value: + $ref: '#/components/schemas/IndexPatternArray' + required: + - type + - value + BulkActionEditPayloadInvestigationFields: + type: object + properties: + type: + enum: + - add_investigation_fields + - delete_investigation_fields + - set_investigation_fields + type: string + value: + $ref: '#/components/schemas/InvestigationFields' + required: + - type + - value + BulkActionEditPayloadRuleActions: + type: object + properties: + type: + enum: + - add_rule_actions + - set_rule_actions + type: string + value: + type: object + properties: + actions: + items: + $ref: '#/components/schemas/NormalizedRuleAction' + type: array + throttle: + $ref: '#/components/schemas/ThrottleForBulkActions' + required: + - actions + required: + - type + - value + BulkActionEditPayloadSchedule: + type: object + properties: + type: + enum: + - set_schedule + type: string + value: + type: object + properties: + interval: + description: Interval in which the rule is executed + example: 1h + pattern: '^[1-9]\d*[smh]$' + type: string + lookback: + description: Lookback time for the rule + example: 1h + pattern: '^[1-9]\d*[smh]$' + type: string + required: + - interval + - lookback + required: + - type + - value + BulkActionEditPayloadTags: + type: object + properties: + type: + enum: + - add_tags + - delete_tags + - set_tags + type: string + value: + $ref: '#/components/schemas/RuleTagArray' + required: + - type + - value + BulkActionEditPayloadTimeline: + type: object + properties: + type: + enum: + - set_timeline + type: string + value: + type: object + properties: + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + required: + - timeline_id + - timeline_title + required: + - type + - value + BulkActionsDryRunErrCode: + enum: + - IMMUTABLE + - MACHINE_LEARNING_AUTH + - MACHINE_LEARNING_INDEX_PATTERN + - ESQL_INDEX_PATTERN + - INVESTIGATION_FIELDS_FEATURE + type: string + BulkActionSkipResult: + type: object + properties: + id: + type: string + name: + type: string + skip_reason: + $ref: '#/components/schemas/BulkEditSkipReason' + required: + - id + - skip_reason + BulkCrudRulesResponse: + items: + oneOf: + - $ref: '#/components/schemas/RuleResponse' + - $ref: '#/components/schemas/ErrorSchema' + type: array + BulkDeleteRules: + type: object + properties: + action: + enum: + - delete + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkDisableRules: + type: object + properties: + action: + enum: + - disable + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkDuplicateRules: + type: object + properties: + action: + enum: + - duplicate + type: string + duplicate: + type: object + properties: + include_exceptions: + description: Whether to copy exceptions from the original rule + type: boolean + include_expired_exceptions: + description: Whether to copy expired exceptions from the original rule + type: boolean + required: + - include_exceptions + - include_expired_exceptions + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkEditActionResponse: + type: object + properties: + attributes: + type: object + properties: + errors: + items: + $ref: '#/components/schemas/NormalizedRuleError' + type: array + results: + $ref: '#/components/schemas/BulkEditActionResults' + summary: + $ref: '#/components/schemas/BulkEditActionSummary' + required: + - results + - summary + message: + type: string + rules_count: + type: integer + status_code: + type: integer + success: + type: boolean + required: + - attributes + BulkEditActionResults: + type: object + properties: + created: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + deleted: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + skipped: + items: + $ref: '#/components/schemas/BulkActionSkipResult' + type: array + updated: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + required: + - updated + - created + - deleted + - skipped + BulkEditActionSummary: + type: object + properties: + failed: + type: integer + skipped: + type: integer + succeeded: + type: integer + total: + type: integer + required: + - failed + - skipped + - succeeded + - total + BulkEditRules: + type: object + properties: + action: + enum: + - edit + type: string + edit: + description: Array of objects containing the edit operations + items: + $ref: '#/components/schemas/BulkActionEditPayload' + minItems: 1 + type: array + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + - edit + BulkEditSkipReason: + enum: + - RULE_NOT_MODIFIED + type: string + BulkEnableRules: + type: object + properties: + action: + enum: + - enable + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkExportActionResponse: + type: string + BulkExportRules: + type: object + properties: + action: + enum: + - export + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + ConcurrentSearches: + minimum: 1 + type: integer + DataViewId: + type: string + DefaultParams: + type: object + properties: + command: + enum: + - isolate + type: string + comment: + type: string + required: + - command + EcsMapping: + additionalProperties: + type: object + properties: + field: + type: string + value: + oneOf: + - type: string + - items: + type: string + type: array + type: object + EndpointResponseAction: + type: object + properties: + action_type_id: + enum: + - .endpoint + type: string + params: + oneOf: + - $ref: '#/components/schemas/DefaultParams' + - $ref: '#/components/schemas/ProcessesParams' + required: + - action_type_id + - params + EqlOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + event_category_override: + $ref: '#/components/schemas/EventCategoryOverride' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + tiebreaker_field: + $ref: '#/components/schemas/TiebreakerField' + timestamp_field: + $ref: '#/components/schemas/TimestampField' + EqlQueryLanguage: + enum: + - eql + type: string + EqlRequiredFields: + type: object + properties: + language: + $ref: '#/components/schemas/EqlQueryLanguage' + description: Query language to use + query: + $ref: '#/components/schemas/RuleQuery' + description: EQL query to execute + type: + description: Rule type + enum: + - eql + type: string + required: + - type + - query + - language + EqlRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/EqlRuleResponseFields' + EqlRuleCreateFields: + allOf: + - $ref: '#/components/schemas/EqlRequiredFields' + - $ref: '#/components/schemas/EqlOptionalFields' + EqlRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EqlRuleCreateFields' + EqlRulePatchFields: + allOf: + - type: object + properties: + language: + $ref: '#/components/schemas/EqlQueryLanguage' + description: Query language to use + query: + $ref: '#/components/schemas/RuleQuery' + description: EQL query to execute + type: + description: Rule type + enum: + - eql + type: string + - $ref: '#/components/schemas/EqlOptionalFields' + EqlRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/EqlRulePatchFields' + EqlRuleResponseFields: + allOf: + - $ref: '#/components/schemas/EqlRequiredFields' + - $ref: '#/components/schemas/EqlOptionalFields' + EqlRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EqlRuleCreateFields' + ErrorSchema: + additionalProperties: false + type: object + properties: + error: + type: object + properties: + message: + type: string + status_code: + minimum: 400 + type: integer + required: + - status_code + - message + id: + type: string + item_id: + minLength: 1 + type: string + list_id: + minLength: 1 + type: string + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + required: + - error + EsqlQueryLanguage: + enum: + - esql + type: string + EsqlRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/EsqlRuleResponseFields' + EsqlRuleCreateFields: + allOf: + - $ref: '#/components/schemas/EsqlRuleOptionalFields' + - $ref: '#/components/schemas/EsqlRuleRequiredFields' + EsqlRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EsqlRuleCreateFields' + EsqlRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + EsqlRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + language: + $ref: '#/components/schemas/EsqlQueryLanguage' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + query: + $ref: '#/components/schemas/RuleQuery' + description: ESQL query to execute + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + type: + description: Rule type + enum: + - esql + type: string + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/EsqlRuleOptionalFields' + EsqlRuleRequiredFields: + type: object + properties: + language: + $ref: '#/components/schemas/EsqlQueryLanguage' + query: + $ref: '#/components/schemas/RuleQuery' + description: ESQL query to execute + type: + description: Rule type + enum: + - esql + type: string + required: + - type + - language + - query + EsqlRuleResponseFields: + allOf: + - $ref: '#/components/schemas/EsqlRuleOptionalFields' + - $ref: '#/components/schemas/EsqlRuleRequiredFields' + EsqlRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EsqlRuleCreateFields' + EventCategoryOverride: + type: string + ExceptionListType: + description: The exception type + enum: + - detection + - rule_default + - endpoint + - endpoint_trusted_apps + - endpoint_events + - endpoint_host_isolation_exceptions + - endpoint_blocklists + type: string + ExternalRuleSource: + description: >- + Type of rule source for externally sourced rules, i.e. rules that have + an external source, such as the Elastic Prebuilt rules repo. + type: object + properties: + is_customized: + $ref: '#/components/schemas/IsExternalRuleCustomized' + type: + enum: + - external + type: string + required: + - type + - is_customized + FindRulesSortField: + enum: + - created_at + - createdAt + - enabled + - execution_summary.last_execution.date + - execution_summary.last_execution.metrics.execution_gap_duration_s + - execution_summary.last_execution.metrics.total_indexing_duration_ms + - execution_summary.last_execution.metrics.total_search_duration_ms + - execution_summary.last_execution.status + - name + - risk_score + - riskScore + - severity + - updated_at + - updatedAt + type: string + HistoryWindowStart: + $ref: '#/components/schemas/NonEmptyString' + IndexPatternArray: + items: + type: string + type: array + InternalRuleSource: + description: >- + Type of rule source for internally sourced rules, i.e. created within + the Kibana apps. + type: object + properties: + type: + enum: + - internal + type: string + required: + - type + InvestigationFields: + type: object + properties: + field_names: + items: + $ref: '#/components/schemas/NonEmptyString' + minItems: 1 + type: array + required: + - field_names + InvestigationGuide: + description: Notes to help investigate alerts produced by the rule. + type: string + IsExternalRuleCustomized: + description: >- + Determines whether an external/prebuilt rule has been customized by the + user (i.e. any of its fields have been modified and diverged from the + base value). + type: boolean + IsRuleEnabled: + description: Determines whether the rule is enabled. + type: boolean + IsRuleImmutable: + deprecated: true + description: >- + This field determines whether the rule is a prebuilt Elastic rule. It + will be replaced with the `rule_source` field. + type: boolean + ItemsPerSearch: + minimum: 1 + type: integer + KqlQueryLanguage: + enum: + - kuery + - lucene + type: string + MachineLearningJobId: + description: Machine learning job ID + oneOf: + - type: string + - items: + type: string + minItems: 1 + type: array + MachineLearningRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/MachineLearningRuleResponseFields' + MachineLearningRuleCreateFields: + $ref: '#/components/schemas/MachineLearningRuleRequiredFields' + MachineLearningRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/MachineLearningRuleCreateFields' + MachineLearningRulePatchFields: + type: object + properties: + anomaly_threshold: + $ref: '#/components/schemas/AnomalyThreshold' + machine_learning_job_id: + $ref: '#/components/schemas/MachineLearningJobId' + type: + description: Rule type + enum: + - machine_learning + type: string + MachineLearningRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/MachineLearningRulePatchFields' + MachineLearningRuleRequiredFields: + type: object + properties: + anomaly_threshold: + $ref: '#/components/schemas/AnomalyThreshold' + machine_learning_job_id: + $ref: '#/components/schemas/MachineLearningJobId' + type: + description: Rule type + enum: + - machine_learning + type: string + required: + - type + - machine_learning_job_id + - anomaly_threshold + MachineLearningRuleResponseFields: + $ref: '#/components/schemas/MachineLearningRuleRequiredFields' + MachineLearningRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/MachineLearningRuleCreateFields' + MaxSignals: + minimum: 1 + type: integer + NewTermsFields: + items: + type: string + maxItems: 3 + minItems: 1 + type: array + NewTermsRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/NewTermsRuleResponseFields' + NewTermsRuleCreateFields: + allOf: + - $ref: '#/components/schemas/NewTermsRuleRequiredFields' + - $ref: '#/components/schemas/NewTermsRuleOptionalFields' + - $ref: '#/components/schemas/NewTermsRuleDefaultableFields' + NewTermsRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/NewTermsRuleCreateFields' + NewTermsRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + NewTermsRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + NewTermsRulePatchFields: + allOf: + - type: object + properties: + history_window_start: + $ref: '#/components/schemas/HistoryWindowStart' + new_terms_fields: + $ref: '#/components/schemas/NewTermsFields' + query: + $ref: '#/components/schemas/RuleQuery' + type: + description: Rule type + enum: + - new_terms + type: string + - $ref: '#/components/schemas/NewTermsRuleOptionalFields' + - $ref: '#/components/schemas/NewTermsRuleDefaultableFields' + NewTermsRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/NewTermsRulePatchFields' + NewTermsRuleRequiredFields: + type: object + properties: + history_window_start: + $ref: '#/components/schemas/HistoryWindowStart' + new_terms_fields: + $ref: '#/components/schemas/NewTermsFields' + query: + $ref: '#/components/schemas/RuleQuery' + type: + description: Rule type + enum: + - new_terms + type: string + required: + - type + - query + - new_terms_fields + - history_window_start + NewTermsRuleResponseFields: + allOf: + - $ref: '#/components/schemas/NewTermsRuleRequiredFields' + - $ref: '#/components/schemas/NewTermsRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + NewTermsRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/NewTermsRuleCreateFields' + NonEmptyString: + description: A string that is not empty and does not contain only whitespace + minLength: 1 + pattern: ^(?! *$).+$ + type: string + NormalizedRuleAction: + additionalProperties: false + type: object + properties: + alerts_filter: + $ref: '#/components/schemas/RuleActionAlertsFilter' + frequency: + $ref: '#/components/schemas/RuleActionFrequency' + group: + $ref: '#/components/schemas/RuleActionGroup' + id: + $ref: '#/components/schemas/RuleActionId' + params: + $ref: '#/components/schemas/RuleActionParams' + required: + - group + - id + - params + NormalizedRuleError: + type: object + properties: + err_code: + $ref: '#/components/schemas/BulkActionsDryRunErrCode' + message: + type: string + rules: + items: + $ref: '#/components/schemas/RuleDetailsInError' + type: array + status_code: + type: integer + required: + - message + - status_code + - rules + OsqueryParams: + type: object + properties: + ecs_mapping: + $ref: '#/components/schemas/EcsMapping' + pack_id: + type: string + queries: + items: + $ref: '#/components/schemas/OsqueryQuery' + type: array + query: + type: string + saved_query_id: + type: string + timeout: + type: number + OsqueryQuery: + type: object + properties: + ecs_mapping: + $ref: '#/components/schemas/EcsMapping' + id: + description: Query ID + type: string + platform: + type: string + query: + description: Query to execute + type: string + removed: + type: boolean + snapshot: + type: boolean + version: + description: Query version + type: string + required: + - id + - query + OsqueryResponseAction: + type: object + properties: + action_type_id: + enum: + - .osquery + type: string + params: + $ref: '#/components/schemas/OsqueryParams' + required: + - action_type_id + - params + ProcessesParams: + type: object + properties: + command: + enum: + - kill-process + - suspend-process + type: string + comment: + type: string + config: + type: object + properties: + field: + description: Field to use instead of process.pid + type: string + overwrite: + default: true + description: Whether to overwrite field with process.pid + type: boolean + required: + - field + required: + - command + - config + QueryRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/QueryRuleResponseFields' + QueryRuleCreateFields: + allOf: + - $ref: '#/components/schemas/QueryRuleRequiredFields' + - $ref: '#/components/schemas/QueryRuleOptionalFields' + - $ref: '#/components/schemas/QueryRuleDefaultableFields' + QueryRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/QueryRuleCreateFields' + QueryRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + query: + $ref: '#/components/schemas/RuleQuery' + QueryRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + response_actions: + items: + $ref: '#/components/schemas/ResponseAction' + type: array + saved_id: + $ref: '#/components/schemas/SavedQueryId' + QueryRulePatchFields: + allOf: + - type: object + properties: + type: + description: Rule type + enum: + - query + type: string + - $ref: '#/components/schemas/QueryRuleOptionalFields' + - $ref: '#/components/schemas/QueryRuleDefaultableFields' + QueryRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/QueryRulePatchFields' + QueryRuleRequiredFields: + type: object + properties: + type: + description: Rule type + enum: + - query + type: string + required: + - type + QueryRuleResponseFields: + allOf: + - $ref: '#/components/schemas/QueryRuleRequiredFields' + - $ref: '#/components/schemas/QueryRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + query: + $ref: '#/components/schemas/RuleQuery' + required: + - query + - language + QueryRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/QueryRuleCreateFields' + RelatedIntegration: + type: object + properties: + integration: + $ref: '#/components/schemas/NonEmptyString' + package: + $ref: '#/components/schemas/NonEmptyString' + version: + $ref: '#/components/schemas/NonEmptyString' + required: + - package + - version + RelatedIntegrationArray: + items: + $ref: '#/components/schemas/RelatedIntegration' + type: array + RequiredField: + description: Describes an Elasticsearch field that is needed for the rule to function + type: object + properties: + ecs: + description: Whether the field is an ECS field + type: boolean + name: + $ref: '#/components/schemas/NonEmptyString' + description: Name of an Elasticsearch field + type: + $ref: '#/components/schemas/NonEmptyString' + description: Type of the Elasticsearch field + required: + - name + - type + - ecs + RequiredFieldArray: + items: + $ref: '#/components/schemas/RequiredField' + type: array + RequiredFieldInput: + description: >- + Input parameters to create a RequiredField. Does not include the `ecs` + field, because `ecs` is calculated on the backend based on the field + name and type. + type: object + properties: + name: + $ref: '#/components/schemas/NonEmptyString' + description: Name of an Elasticsearch field + type: + $ref: '#/components/schemas/NonEmptyString' + description: Type of an Elasticsearch field + required: + - name + - type + ResponseAction: + oneOf: + - $ref: '#/components/schemas/OsqueryResponseAction' + - $ref: '#/components/schemas/EndpointResponseAction' + ResponseFields: + type: object + properties: + created_at: + format: date-time + type: string + created_by: + type: string + execution_summary: + $ref: '#/components/schemas/RuleExecutionSummary' + id: + $ref: '#/components/schemas/RuleObjectId' + immutable: + $ref: '#/components/schemas/IsRuleImmutable' + required_fields: + $ref: '#/components/schemas/RequiredFieldArray' + revision: + minimum: 0 + type: integer + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_source: + $ref: '#/components/schemas/RuleSource' + updated_at: + format: date-time + type: string + updated_by: + type: string + required: + - id + - rule_id + - immutable + - updated_at + - updated_by + - created_at + - created_by + - revision + - related_integrations + - required_fields + RiskScore: + description: Risk score (0 to 100) + maximum: 100 + minimum: 0 + type: integer + RiskScoreMapping: + description: >- + Overrides generated alerts' risk_score with a value from the source + event + items: + type: object + properties: + field: + type: string + operator: + enum: + - equals + type: string + risk_score: + $ref: '#/components/schemas/RiskScore' + value: + type: string + required: + - field + - operator + - value + type: array + RuleAction: + type: object + properties: + action_type_id: + description: The action type used for sending notifications. + type: string + alerts_filter: + $ref: '#/components/schemas/RuleActionAlertsFilter' + frequency: + $ref: '#/components/schemas/RuleActionFrequency' + group: + $ref: '#/components/schemas/RuleActionGroup' + id: + $ref: '#/components/schemas/RuleActionId' + params: + $ref: '#/components/schemas/RuleActionParams' + uuid: + $ref: '#/components/schemas/NonEmptyString' + required: + - action_type_id + - group + - id + - params + RuleActionAlertsFilter: + additionalProperties: true + type: object + RuleActionFrequency: + description: >- + The action frequency defines when the action runs (for example, only on + rule execution or at specific time intervals). + type: object + properties: + notifyWhen: + $ref: '#/components/schemas/RuleActionNotifyWhen' + summary: + description: >- + Action summary indicates whether we will send a summary notification + about all the generate alerts or notification per individual alert + type: boolean + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + nullable: true + required: + - summary + - notifyWhen + - throttle + RuleActionGroup: + description: >- + Optionally groups actions by use cases. Use `default` for alert + notifications. + type: string + RuleActionId: + description: The connector ID. + type: string + RuleActionNotifyWhen: + description: >- + The condition for throttling the notification: `onActionGroupChange`, + `onActiveAlert`, or `onThrottleInterval` + enum: + - onActiveAlert + - onThrottleInterval + - onActionGroupChange + type: string + RuleActionParams: + additionalProperties: true + description: >- + Object containing the allowed connector fields, which varies according + to the connector type. + type: object + RuleActionThrottle: + description: Defines the interval on which a rule's actions are executed. + oneOf: + - enum: + - no_actions + - rule + type: string + - description: 'Time interval in seconds, minutes, hours, or days.' + example: 1h + pattern: '^[1-9]\d*[smhd]$' + type: string + RuleAuthorArray: + items: + type: string + type: array + RuleCreateProps: + anyOf: + - $ref: '#/components/schemas/EqlRuleCreateProps' + - $ref: '#/components/schemas/QueryRuleCreateProps' + - $ref: '#/components/schemas/SavedQueryRuleCreateProps' + - $ref: '#/components/schemas/ThresholdRuleCreateProps' + - $ref: '#/components/schemas/ThreatMatchRuleCreateProps' + - $ref: '#/components/schemas/MachineLearningRuleCreateProps' + - $ref: '#/components/schemas/NewTermsRuleCreateProps' + - $ref: '#/components/schemas/EsqlRuleCreateProps' + discriminator: + propertyName: type + RuleDescription: + minLength: 1 + type: string + RuleDetailsInError: + type: object + properties: + id: + type: string + name: + type: string + required: + - id + RuleExceptionList: + type: object + properties: + id: + $ref: '#/components/schemas/NonEmptyString' + description: ID of the exception container + list_id: + $ref: '#/components/schemas/NonEmptyString' + description: List ID of the exception container + namespace_type: + description: Determines the exceptions validity in rule's Kibana space + enum: + - agnostic + - single + type: string + type: + $ref: '#/components/schemas/ExceptionListType' + required: + - id + - list_id + - type + - namespace_type + RuleExecutionMetrics: + type: object + properties: + execution_gap_duration_s: + description: Duration in seconds of execution gap + minimum: 0 + type: integer + total_enrichment_duration_ms: + description: >- + Total time spent enriching documents during current rule execution + cycle + minimum: 0 + type: integer + total_indexing_duration_ms: + description: >- + Total time spent indexing documents during current rule execution + cycle + minimum: 0 + type: integer + total_search_duration_ms: + description: >- + Total time spent performing ES searches as measured by Kibana; + includes network latency and time spent serializing/deserializing + request/response + minimum: 0 + type: integer + RuleExecutionStatus: + description: >- + Custom execution status of Security rules that is different from the + status used in the Alerting Framework. We merge our custom status with + the Framework's status to determine the resulting status of a rule. + + - going to run - @deprecated Replaced by the 'running' status but left + for backwards compatibility with rule execution events already written + to Event Log in the prior versions of Kibana. Don't use when writing + rule status changes. + + - running - Rule execution started but not reached any intermediate or + final status. + + - partial failure - Rule can partially fail for various reasons either + in the middle of an execution (in this case we update its status right + away) or in the end of it. So currently this status can be both + intermediate and final at the same time. A typical reason for a partial + failure: not all the indices that the rule searches over actually exist. + + - failed - Rule failed to execute due to unhandled exception or a reason + defined in the business logic of its executor function. + + - succeeded - Rule executed successfully without any issues. Note: this + status is just an indication of a rule's "health". The rule might or + might not generate any alerts despite of it. + enum: + - going to run + - running + - partial failure + - failed + - succeeded + type: string + RuleExecutionStatusOrder: + type: integer + RuleExecutionSummary: + type: object + properties: + last_execution: + type: object + properties: + date: + description: Date of the last execution + format: date-time + type: string + message: + type: string + metrics: + $ref: '#/components/schemas/RuleExecutionMetrics' + status: + $ref: '#/components/schemas/RuleExecutionStatus' + description: Status of the last execution + status_order: + $ref: '#/components/schemas/RuleExecutionStatusOrder' + required: + - date + - status + - status_order + - message + - metrics + required: + - last_execution + RuleFalsePositiveArray: + items: + type: string + type: array + RuleFilterArray: + items: {} + type: array + RuleInterval: + description: >- + Frequency of rule execution, using a date math range. For example, "1h" + means the rule runs every hour. Defaults to 5m (5 minutes). + type: string + RuleIntervalFrom: + description: >- + Time from which data is analyzed each time the rule executes, using a + date math range. For example, now-4200s means the rule analyzes data + from 70 minutes before its start time. Defaults to now-6m (analyzes data + from 6 minutes before the start time). + format: date-math + type: string + RuleIntervalTo: + type: string + RuleLicense: + description: The rule's license. + type: string + RuleMetadata: + additionalProperties: true + type: object + RuleName: + minLength: 1 + type: string + RuleNameOverride: + description: Sets the source field for the alert's signal.rule.name value + type: string + RuleObjectId: + $ref: '#/components/schemas/UUID' + RulePatchProps: + anyOf: + - $ref: '#/components/schemas/EqlRulePatchProps' + - $ref: '#/components/schemas/QueryRulePatchProps' + - $ref: '#/components/schemas/SavedQueryRulePatchProps' + - $ref: '#/components/schemas/ThresholdRulePatchProps' + - $ref: '#/components/schemas/ThreatMatchRulePatchProps' + - $ref: '#/components/schemas/MachineLearningRulePatchProps' + - $ref: '#/components/schemas/NewTermsRulePatchProps' + - $ref: '#/components/schemas/EsqlRulePatchProps' + RuleQuery: + type: string + RuleReferenceArray: + items: + type: string + type: array + RuleResponse: + anyOf: + - $ref: '#/components/schemas/EqlRule' + - $ref: '#/components/schemas/QueryRule' + - $ref: '#/components/schemas/SavedQueryRule' + - $ref: '#/components/schemas/ThresholdRule' + - $ref: '#/components/schemas/ThreatMatchRule' + - $ref: '#/components/schemas/MachineLearningRule' + - $ref: '#/components/schemas/NewTermsRule' + - $ref: '#/components/schemas/EsqlRule' + discriminator: + propertyName: type + RuleSignatureId: + description: 'Could be any string, not necessarily a UUID' + type: string + RuleSource: + description: >- + Discriminated union that determines whether the rule is internally + sourced (created within the Kibana app) or has an external source, such + as the Elastic Prebuilt rules repo. + discriminator: + propertyName: type + oneOf: + - $ref: '#/components/schemas/ExternalRuleSource' + - $ref: '#/components/schemas/InternalRuleSource' + RuleTagArray: + description: >- + String array containing words and phrases to help categorize, filter, + and search rules. Defaults to an empty array. + items: + type: string + type: array + RuleUpdateProps: + anyOf: + - $ref: '#/components/schemas/EqlRuleUpdateProps' + - $ref: '#/components/schemas/QueryRuleUpdateProps' + - $ref: '#/components/schemas/SavedQueryRuleUpdateProps' + - $ref: '#/components/schemas/ThresholdRuleUpdateProps' + - $ref: '#/components/schemas/ThreatMatchRuleUpdateProps' + - $ref: '#/components/schemas/MachineLearningRuleUpdateProps' + - $ref: '#/components/schemas/NewTermsRuleUpdateProps' + - $ref: '#/components/schemas/EsqlRuleUpdateProps' + discriminator: + propertyName: type + RuleVersion: + description: The rule's version number. + minimum: 1 + type: integer + SavedObjectResolveAliasPurpose: + enum: + - savedObjectConversion + - savedObjectImport + type: string + SavedObjectResolveAliasTargetId: + type: string + SavedObjectResolveOutcome: + enum: + - exactMatch + - aliasMatch + - conflict + type: string + SavedQueryId: + type: string + SavedQueryRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/SavedQueryRuleResponseFields' + SavedQueryRuleCreateFields: + allOf: + - $ref: '#/components/schemas/SavedQueryRuleRequiredFields' + - $ref: '#/components/schemas/SavedQueryRuleOptionalFields' + - $ref: '#/components/schemas/SavedQueryRuleDefaultableFields' + SavedQueryRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/SavedQueryRuleCreateFields' + SavedQueryRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + SavedQueryRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + query: + $ref: '#/components/schemas/RuleQuery' + response_actions: + items: + $ref: '#/components/schemas/ResponseAction' + type: array + SavedQueryRulePatchFields: + allOf: + - type: object + properties: + saved_id: + $ref: '#/components/schemas/SavedQueryId' + type: + description: Rule type + enum: + - saved_query + type: string + - $ref: '#/components/schemas/SavedQueryRuleOptionalFields' + - $ref: '#/components/schemas/SavedQueryRuleDefaultableFields' + SavedQueryRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/SavedQueryRulePatchFields' + SavedQueryRuleRequiredFields: + type: object + properties: + saved_id: + $ref: '#/components/schemas/SavedQueryId' + type: + description: Rule type + enum: + - saved_query + type: string + required: + - type + - saved_id + SavedQueryRuleResponseFields: + allOf: + - $ref: '#/components/schemas/SavedQueryRuleRequiredFields' + - $ref: '#/components/schemas/SavedQueryRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + SavedQueryRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/SavedQueryRuleCreateFields' + SetupGuide: + type: string + Severity: + description: Severity of the rule + enum: + - low + - medium + - high + - critical + type: string + SeverityMapping: + description: Overrides generated alerts' severity with values from the source event + items: + type: object + properties: + field: + type: string + operator: + enum: + - equals + type: string + severity: + $ref: '#/components/schemas/Severity' + value: + type: string + required: + - field + - operator + - severity + - value + type: array + SortOrder: + enum: + - asc + - desc + type: string + Threat: + type: object + properties: + framework: + description: Relevant attack framework + type: string + tactic: + $ref: '#/components/schemas/ThreatTactic' + technique: + description: Array containing information on the attack techniques (optional) + items: + $ref: '#/components/schemas/ThreatTechnique' + type: array + required: + - framework + - tactic + ThreatArray: + items: + $ref: '#/components/schemas/Threat' + type: array + ThreatFilters: + items: + description: >- + Query and filter context array used to filter documents from the + Elasticsearch index containing the threat values + type: array + ThreatIndex: + items: + type: string + type: array + ThreatIndicatorPath: + description: >- + Defines the path to the threat indicator in the indicator documents + (optional) + type: string + ThreatMapping: + items: + type: object + properties: + entries: + items: + type: object + properties: + field: + $ref: '#/components/schemas/NonEmptyString' + type: + enum: + - mapping + type: string + value: + $ref: '#/components/schemas/NonEmptyString' + required: + - field + - type + - value + type: array + required: + - entries + minItems: 1 + type: array + ThreatMatchRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/ThreatMatchRuleResponseFields' + ThreatMatchRuleCreateFields: + allOf: + - $ref: '#/components/schemas/ThreatMatchRuleRequiredFields' + - $ref: '#/components/schemas/ThreatMatchRuleOptionalFields' + - $ref: '#/components/schemas/ThreatMatchRuleDefaultableFields' + ThreatMatchRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThreatMatchRuleCreateFields' + ThreatMatchRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + ThreatMatchRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + concurrent_searches: + $ref: '#/components/schemas/ConcurrentSearches' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + items_per_search: + $ref: '#/components/schemas/ItemsPerSearch' + saved_id: + $ref: '#/components/schemas/SavedQueryId' + threat_filters: + $ref: '#/components/schemas/ThreatFilters' + threat_indicator_path: + $ref: '#/components/schemas/ThreatIndicatorPath' + threat_language: + $ref: '#/components/schemas/KqlQueryLanguage' + ThreatMatchRulePatchFields: + allOf: + - type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threat_index: + $ref: '#/components/schemas/ThreatIndex' + threat_mapping: + $ref: '#/components/schemas/ThreatMapping' + threat_query: + $ref: '#/components/schemas/ThreatQuery' + type: + description: Rule type + enum: + - threat_match + type: string + - $ref: '#/components/schemas/ThreatMatchRuleOptionalFields' + - $ref: '#/components/schemas/ThreatMatchRuleDefaultableFields' + ThreatMatchRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/ThreatMatchRulePatchFields' + ThreatMatchRuleRequiredFields: + type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threat_index: + $ref: '#/components/schemas/ThreatIndex' + threat_mapping: + $ref: '#/components/schemas/ThreatMapping' + threat_query: + $ref: '#/components/schemas/ThreatQuery' + type: + description: Rule type + enum: + - threat_match + type: string + required: + - type + - query + - threat_query + - threat_mapping + - threat_index + ThreatMatchRuleResponseFields: + allOf: + - $ref: '#/components/schemas/ThreatMatchRuleRequiredFields' + - $ref: '#/components/schemas/ThreatMatchRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + ThreatMatchRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThreatMatchRuleCreateFields' + ThreatQuery: + description: Query to execute + type: string + ThreatSubtechnique: + type: object + properties: + id: + description: Subtechnique ID + type: string + name: + description: Subtechnique name + type: string + reference: + description: Subtechnique reference + type: string + required: + - id + - name + - reference + ThreatTactic: + type: object + properties: + id: + description: Tactic ID + type: string + name: + description: Tactic name + type: string + reference: + description: Tactic reference + type: string + required: + - id + - name + - reference + ThreatTechnique: + type: object + properties: + id: + description: Technique ID + type: string + name: + description: Technique name + type: string + reference: + description: Technique reference + type: string + subtechnique: + description: Array containing more specific information on the attack technique + items: + $ref: '#/components/schemas/ThreatSubtechnique' + type: array + required: + - id + - name + - reference + Threshold: + type: object + properties: + cardinality: + $ref: '#/components/schemas/ThresholdCardinality' + field: + $ref: '#/components/schemas/ThresholdField' + value: + $ref: '#/components/schemas/ThresholdValue' + required: + - field + - value + ThresholdAlertSuppression: + type: object + properties: + duration: + $ref: '#/components/schemas/AlertSuppressionDuration' + required: + - duration + ThresholdCardinality: + items: + type: object + properties: + field: + type: string + value: + minimum: 0 + type: integer + required: + - field + - value + type: array + ThresholdField: + description: Field to aggregate on + oneOf: + - type: string + - items: + type: string + type: array + ThresholdRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/ThresholdRuleResponseFields' + ThresholdRuleCreateFields: + allOf: + - $ref: '#/components/schemas/ThresholdRuleRequiredFields' + - $ref: '#/components/schemas/ThresholdRuleOptionalFields' + - $ref: '#/components/schemas/ThresholdRuleDefaultableFields' + ThresholdRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThresholdRuleCreateFields' + ThresholdRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + ThresholdRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/ThresholdAlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + saved_id: + $ref: '#/components/schemas/SavedQueryId' + ThresholdRulePatchFields: + allOf: + - type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threshold: + $ref: '#/components/schemas/Threshold' + type: + description: Rule type + enum: + - threshold + type: string + - $ref: '#/components/schemas/ThresholdRuleOptionalFields' + - $ref: '#/components/schemas/ThresholdRuleDefaultableFields' + ThresholdRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/ThresholdRulePatchFields' + ThresholdRuleRequiredFields: + type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threshold: + $ref: '#/components/schemas/Threshold' + type: + description: Rule type + enum: + - threshold + type: string + required: + - type + - query + - threshold + ThresholdRuleResponseFields: + allOf: + - $ref: '#/components/schemas/ThresholdRuleRequiredFields' + - $ref: '#/components/schemas/ThresholdRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + ThresholdRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThresholdRuleCreateFields' + ThresholdValue: + description: Threshold value + minimum: 1 + type: integer + ThrottleForBulkActions: + description: >- + The condition for throttling the notification: 'rule', 'no_actions', or + time duration + enum: + - rule + - 1h + - 1d + - 7d + type: string + TiebreakerField: + description: Sets a secondary field for sorting events + type: string + TimelineTemplateId: + description: Timeline template ID + type: string + TimelineTemplateTitle: + description: Timeline template title + type: string + TimestampField: + description: Contains the event timestamp used for sorting a sequence of events + type: string + TimestampOverride: + description: Sets the time field used to query indices + type: string + TimestampOverrideFallbackDisabled: + description: Disables the fallback to the event's @timestamp field + type: boolean + UUID: + description: A universally unique identifier + format: uuid + type: string + WarningSchema: + type: object + properties: + actionPath: + type: string + buttonLabel: + type: string + message: + type: string + type: + type: string + required: + - type + - message + - actionPath + securitySchemes: + BasicAuth: + scheme: basic + type: http +security: + - BasicAuth: [] diff --git a/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml b/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml new file mode 100644 index 0000000000000..94682a8e1b8f9 --- /dev/null +++ b/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml @@ -0,0 +1,5485 @@ +openapi: 3.0.3 +info: + description: >- + You can create rules that automatically turn events and external alerts sent + to Elastic Security into detection alerts. These alerts are displayed on the + Detections page. + title: Security Solution Detections API (Elastic Cloud Serverless) + version: '2023-10-31' +servers: + - url: 'http://{kibana_host}:{port}' + variables: + kibana_host: + default: localhost + port: + default: '5601' +paths: + /api/detection_engine/rules: + delete: + description: Deletes a single rule using the `rule_id` or `id` field. + operationId: DeleteRule + parameters: + - description: The rule's `id` value. + in: query + name: id + required: false + schema: + $ref: '#/components/schemas/RuleObjectId' + - description: The rule's `rule_id` value. + in: query + name: rule_id + required: false + schema: + $ref: '#/components/schemas/RuleSignatureId' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + get: + description: Read a single rule + operationId: ReadRule + parameters: + - description: The rule's `id` value. + in: query + name: id + required: false + schema: + $ref: '#/components/schemas/RuleObjectId' + - description: The rule's `rule_id` value. + in: query + name: rule_id + required: false + schema: + $ref: '#/components/schemas/RuleSignatureId' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + patch: + description: Patch a single rule + operationId: PatchRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RulePatchProps' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + post: + description: Create a single detection rule + operationId: CreateRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RuleCreateProps' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + put: + description: Update a single rule + operationId: UpdateRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RuleUpdateProps' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleResponse' + description: Indicates a successful call. + tags: + - Rules API + /api/detection_engine/rules/_bulk_action: + post: + description: >- + The bulk action is applied to all rules that match the filter or to the + list of rules by their IDs. + operationId: PerformBulkAction + parameters: + - description: Enables dry run mode for the request call. + in: query + name: dry_run + required: false + schema: + type: boolean + requestBody: + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/BulkDeleteRules' + - $ref: '#/components/schemas/BulkDisableRules' + - $ref: '#/components/schemas/BulkEnableRules' + - $ref: '#/components/schemas/BulkExportRules' + - $ref: '#/components/schemas/BulkDuplicateRules' + - $ref: '#/components/schemas/BulkEditRules' + responses: + '200': + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/BulkEditActionResponse' + - $ref: '#/components/schemas/BulkExportActionResponse' + description: OK + summary: Applies a bulk action to multiple rules + tags: + - Bulk API + /api/detection_engine/rules/_export: + post: + description: >- + Exports rules to an `.ndjson` file. The following configuration items + are also included in the `.ndjson` file - Actions, Exception lists. + Prebuilt rules cannot be exported. + operationId: ExportRules + parameters: + - description: Determines whether a summary of the exported rules is returned. + in: query + name: exclude_export_details + required: false + schema: + default: false + type: boolean + - description: File name for saving the exported rules. + in: query + name: file_name + required: false + schema: + default: export.ndjson + type: string + requestBody: + content: + application/json: + schema: + nullable: true + type: object + properties: + objects: + description: >- + Array of `rule_id` fields. Exports all rules when + unspecified. + items: + type: object + properties: + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + required: + - rule_id + type: array + required: + - objects + required: false + responses: + '200': + content: + application/ndjson: + schema: + description: An `.ndjson` file containing the returned rules. + format: binary + type: string + description: Indicates a successful call. + summary: Export rules + tags: + - Import/Export API + summary: Exports rules to an `.ndjson` file + /api/detection_engine/rules/_find: + get: + description: Finds rules that match the given query. + operationId: FindRules + parameters: + - in: query + name: fields + required: false + schema: + items: + type: string + type: array + - description: Search query + in: query + name: filter + required: false + schema: + type: string + - description: Field to sort by + in: query + name: sort_field + required: false + schema: + $ref: '#/components/schemas/FindRulesSortField' + - description: Sort order + in: query + name: sort_order + required: false + schema: + $ref: '#/components/schemas/SortOrder' + - description: Page number + in: query + name: page + required: false + schema: + default: 1 + minimum: 1 + type: integer + - description: Rules per page + in: query + name: per_page + required: false + schema: + default: 20 + minimum: 0 + type: integer + responses: + '200': + content: + application/json: + schema: + type: object + properties: + data: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + page: + type: integer + perPage: + type: integer + total: + type: integer + required: + - page + - perPage + - total + - data + description: Successful response + tags: + - Rules API + /api/detection_engine/rules/_import: + post: + description: >- + Imports rules from an `.ndjson` file, including actions and exception + lists. + operationId: ImportRules + parameters: + - description: >- + Determines whether existing rules with the same `rule_id` are + overwritten. + in: query + name: overwrite + required: false + schema: + default: false + type: boolean + - description: >- + Determines whether existing exception lists with the same `list_id` + are overwritten. + in: query + name: overwrite_exceptions + required: false + schema: + default: false + type: boolean + - description: >- + Determines whether existing actions with the same + `kibana.alert.rule.actions.id` are overwritten. + in: query + name: overwrite_action_connectors + required: false + schema: + default: false + type: boolean + - description: Generates a new list ID for each imported exception list. + in: query + name: as_new_list + required: false + schema: + default: false + type: boolean + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + description: The `.ndjson` file containing the rules. + format: binary + type: string + required: true + responses: + '200': + content: + application/json: + schema: + additionalProperties: false + type: object + properties: + action_connectors_errors: + items: + $ref: '#/components/schemas/ErrorSchema' + type: array + action_connectors_success: + type: boolean + action_connectors_success_count: + minimum: 0 + type: integer + action_connectors_warnings: + items: + $ref: '#/components/schemas/WarningSchema' + type: array + errors: + items: + $ref: '#/components/schemas/ErrorSchema' + type: array + exceptions_errors: + items: + $ref: '#/components/schemas/ErrorSchema' + type: array + exceptions_success: + type: boolean + exceptions_success_count: + minimum: 0 + type: integer + rules_count: + minimum: 0 + type: integer + success: + type: boolean + success_count: + minimum: 0 + type: integer + required: + - exceptions_success + - exceptions_success_count + - exceptions_errors + - rules_count + - success + - success_count + - errors + - action_connectors_errors + - action_connectors_warnings + - action_connectors_success + - action_connectors_success_count + description: Indicates a successful call. + summary: Import rules + tags: + - Import/Export API + summary: Imports rules from an `.ndjson` file + /api/detection_engine/signals/assignees: + post: + description: Assigns users to alerts. + operationId: SetAlertAssignees + requestBody: + content: + application/json: + schema: + type: object + properties: + assignees: + $ref: '#/components/schemas/AlertAssignees' + description: Details about the assignees to assign and unassign. + ids: + $ref: '#/components/schemas/AlertIds' + description: List of alerts ids to assign and unassign passed assignees. + required: + - assignees + - ids + required: true + responses: + '200': + description: Indicates a successful call. + '400': + description: Invalid request. + summary: Assigns users to alerts + /api/detection_engine/tags: + get: + operationId: ReadTags + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/RuleTagArray' + description: Indicates a successful call + summary: Aggregates and returns all unique tags from all rules + tags: + - Tags API + summary: Aggregates and returns rule tags +components: + schemas: + AlertAssignees: + type: object + properties: + add: + description: A list of users ids to assign. + items: + $ref: '#/components/schemas/NonEmptyString' + type: array + remove: + description: A list of users ids to unassign. + items: + $ref: '#/components/schemas/NonEmptyString' + type: array + required: + - add + - remove + AlertIds: + description: A list of alerts ids. + items: + $ref: '#/components/schemas/NonEmptyString' + minItems: 1 + type: array + AlertsIndex: + deprecated: true + description: (deprecated) Has no effect. + type: string + AlertsIndexNamespace: + description: Has no effect. + type: string + AlertSuppression: + type: object + properties: + duration: + $ref: '#/components/schemas/AlertSuppressionDuration' + group_by: + $ref: '#/components/schemas/AlertSuppressionGroupBy' + missing_fields_strategy: + $ref: '#/components/schemas/AlertSuppressionMissingFieldsStrategy' + required: + - group_by + AlertSuppressionDuration: + type: object + properties: + unit: + enum: + - s + - m + - h + type: string + value: + minimum: 1 + type: integer + required: + - value + - unit + AlertSuppressionGroupBy: + items: + type: string + maxItems: 3 + minItems: 1 + type: array + AlertSuppressionMissingFieldsStrategy: + description: >- + Describes how alerts will be generated for documents with missing + suppress by fields: + + doNotSuppress - per each document a separate alert will be created + + suppress - only alert will be created per suppress by bucket + enum: + - doNotSuppress + - suppress + type: string + AnomalyThreshold: + description: Anomaly threshold + minimum: 0 + type: integer + BuildingBlockType: + description: >- + Determines if the rule acts as a building block. By default, + building-block alerts are not displayed in the UI. These rules are used + as a foundation for other rules that do generate alerts. Its value must + be default. + type: string + BulkActionEditPayload: + anyOf: + - $ref: '#/components/schemas/BulkActionEditPayloadTags' + - $ref: '#/components/schemas/BulkActionEditPayloadIndexPatterns' + - $ref: '#/components/schemas/BulkActionEditPayloadInvestigationFields' + - $ref: '#/components/schemas/BulkActionEditPayloadTimeline' + - $ref: '#/components/schemas/BulkActionEditPayloadRuleActions' + - $ref: '#/components/schemas/BulkActionEditPayloadSchedule' + BulkActionEditPayloadIndexPatterns: + type: object + properties: + overwrite_data_views: + type: boolean + type: + enum: + - add_index_patterns + - delete_index_patterns + - set_index_patterns + type: string + value: + $ref: '#/components/schemas/IndexPatternArray' + required: + - type + - value + BulkActionEditPayloadInvestigationFields: + type: object + properties: + type: + enum: + - add_investigation_fields + - delete_investigation_fields + - set_investigation_fields + type: string + value: + $ref: '#/components/schemas/InvestigationFields' + required: + - type + - value + BulkActionEditPayloadRuleActions: + type: object + properties: + type: + enum: + - add_rule_actions + - set_rule_actions + type: string + value: + type: object + properties: + actions: + items: + $ref: '#/components/schemas/NormalizedRuleAction' + type: array + throttle: + $ref: '#/components/schemas/ThrottleForBulkActions' + required: + - actions + required: + - type + - value + BulkActionEditPayloadSchedule: + type: object + properties: + type: + enum: + - set_schedule + type: string + value: + type: object + properties: + interval: + description: Interval in which the rule is executed + example: 1h + pattern: '^[1-9]\d*[smh]$' + type: string + lookback: + description: Lookback time for the rule + example: 1h + pattern: '^[1-9]\d*[smh]$' + type: string + required: + - interval + - lookback + required: + - type + - value + BulkActionEditPayloadTags: + type: object + properties: + type: + enum: + - add_tags + - delete_tags + - set_tags + type: string + value: + $ref: '#/components/schemas/RuleTagArray' + required: + - type + - value + BulkActionEditPayloadTimeline: + type: object + properties: + type: + enum: + - set_timeline + type: string + value: + type: object + properties: + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + required: + - timeline_id + - timeline_title + required: + - type + - value + BulkActionsDryRunErrCode: + enum: + - IMMUTABLE + - MACHINE_LEARNING_AUTH + - MACHINE_LEARNING_INDEX_PATTERN + - ESQL_INDEX_PATTERN + - INVESTIGATION_FIELDS_FEATURE + type: string + BulkActionSkipResult: + type: object + properties: + id: + type: string + name: + type: string + skip_reason: + $ref: '#/components/schemas/BulkEditSkipReason' + required: + - id + - skip_reason + BulkDeleteRules: + type: object + properties: + action: + enum: + - delete + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkDisableRules: + type: object + properties: + action: + enum: + - disable + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkDuplicateRules: + type: object + properties: + action: + enum: + - duplicate + type: string + duplicate: + type: object + properties: + include_exceptions: + description: Whether to copy exceptions from the original rule + type: boolean + include_expired_exceptions: + description: Whether to copy expired exceptions from the original rule + type: boolean + required: + - include_exceptions + - include_expired_exceptions + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkEditActionResponse: + type: object + properties: + attributes: + type: object + properties: + errors: + items: + $ref: '#/components/schemas/NormalizedRuleError' + type: array + results: + $ref: '#/components/schemas/BulkEditActionResults' + summary: + $ref: '#/components/schemas/BulkEditActionSummary' + required: + - results + - summary + message: + type: string + rules_count: + type: integer + status_code: + type: integer + success: + type: boolean + required: + - attributes + BulkEditActionResults: + type: object + properties: + created: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + deleted: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + skipped: + items: + $ref: '#/components/schemas/BulkActionSkipResult' + type: array + updated: + items: + $ref: '#/components/schemas/RuleResponse' + type: array + required: + - updated + - created + - deleted + - skipped + BulkEditActionSummary: + type: object + properties: + failed: + type: integer + skipped: + type: integer + succeeded: + type: integer + total: + type: integer + required: + - failed + - skipped + - succeeded + - total + BulkEditRules: + type: object + properties: + action: + enum: + - edit + type: string + edit: + description: Array of objects containing the edit operations + items: + $ref: '#/components/schemas/BulkActionEditPayload' + minItems: 1 + type: array + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + - edit + BulkEditSkipReason: + enum: + - RULE_NOT_MODIFIED + type: string + BulkEnableRules: + type: object + properties: + action: + enum: + - enable + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + BulkExportActionResponse: + type: string + BulkExportRules: + type: object + properties: + action: + enum: + - export + type: string + ids: + description: Array of rule IDs + items: + type: string + minItems: 1 + type: array + query: + description: Query to filter rules + type: string + required: + - action + ConcurrentSearches: + minimum: 1 + type: integer + DataViewId: + type: string + DefaultParams: + type: object + properties: + command: + enum: + - isolate + type: string + comment: + type: string + required: + - command + EcsMapping: + additionalProperties: + type: object + properties: + field: + type: string + value: + oneOf: + - type: string + - items: + type: string + type: array + type: object + EndpointResponseAction: + type: object + properties: + action_type_id: + enum: + - .endpoint + type: string + params: + oneOf: + - $ref: '#/components/schemas/DefaultParams' + - $ref: '#/components/schemas/ProcessesParams' + required: + - action_type_id + - params + EqlOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + event_category_override: + $ref: '#/components/schemas/EventCategoryOverride' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + tiebreaker_field: + $ref: '#/components/schemas/TiebreakerField' + timestamp_field: + $ref: '#/components/schemas/TimestampField' + EqlQueryLanguage: + enum: + - eql + type: string + EqlRequiredFields: + type: object + properties: + language: + $ref: '#/components/schemas/EqlQueryLanguage' + description: Query language to use + query: + $ref: '#/components/schemas/RuleQuery' + description: EQL query to execute + type: + description: Rule type + enum: + - eql + type: string + required: + - type + - query + - language + EqlRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/EqlRuleResponseFields' + EqlRuleCreateFields: + allOf: + - $ref: '#/components/schemas/EqlRequiredFields' + - $ref: '#/components/schemas/EqlOptionalFields' + EqlRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EqlRuleCreateFields' + EqlRulePatchFields: + allOf: + - type: object + properties: + language: + $ref: '#/components/schemas/EqlQueryLanguage' + description: Query language to use + query: + $ref: '#/components/schemas/RuleQuery' + description: EQL query to execute + type: + description: Rule type + enum: + - eql + type: string + - $ref: '#/components/schemas/EqlOptionalFields' + EqlRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/EqlRulePatchFields' + EqlRuleResponseFields: + allOf: + - $ref: '#/components/schemas/EqlRequiredFields' + - $ref: '#/components/schemas/EqlOptionalFields' + EqlRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EqlRuleCreateFields' + ErrorSchema: + additionalProperties: false + type: object + properties: + error: + type: object + properties: + message: + type: string + status_code: + minimum: 400 + type: integer + required: + - status_code + - message + id: + type: string + item_id: + minLength: 1 + type: string + list_id: + minLength: 1 + type: string + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + required: + - error + EsqlQueryLanguage: + enum: + - esql + type: string + EsqlRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/EsqlRuleResponseFields' + EsqlRuleCreateFields: + allOf: + - $ref: '#/components/schemas/EsqlRuleOptionalFields' + - $ref: '#/components/schemas/EsqlRuleRequiredFields' + EsqlRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EsqlRuleCreateFields' + EsqlRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + EsqlRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + language: + $ref: '#/components/schemas/EsqlQueryLanguage' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + query: + $ref: '#/components/schemas/RuleQuery' + description: ESQL query to execute + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + type: + description: Rule type + enum: + - esql + type: string + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/EsqlRuleOptionalFields' + EsqlRuleRequiredFields: + type: object + properties: + language: + $ref: '#/components/schemas/EsqlQueryLanguage' + query: + $ref: '#/components/schemas/RuleQuery' + description: ESQL query to execute + type: + description: Rule type + enum: + - esql + type: string + required: + - type + - language + - query + EsqlRuleResponseFields: + allOf: + - $ref: '#/components/schemas/EsqlRuleOptionalFields' + - $ref: '#/components/schemas/EsqlRuleRequiredFields' + EsqlRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/EsqlRuleCreateFields' + EventCategoryOverride: + type: string + ExceptionListType: + description: The exception type + enum: + - detection + - rule_default + - endpoint + - endpoint_trusted_apps + - endpoint_events + - endpoint_host_isolation_exceptions + - endpoint_blocklists + type: string + ExternalRuleSource: + description: >- + Type of rule source for externally sourced rules, i.e. rules that have + an external source, such as the Elastic Prebuilt rules repo. + type: object + properties: + is_customized: + $ref: '#/components/schemas/IsExternalRuleCustomized' + type: + enum: + - external + type: string + required: + - type + - is_customized + FindRulesSortField: + enum: + - created_at + - createdAt + - enabled + - execution_summary.last_execution.date + - execution_summary.last_execution.metrics.execution_gap_duration_s + - execution_summary.last_execution.metrics.total_indexing_duration_ms + - execution_summary.last_execution.metrics.total_search_duration_ms + - execution_summary.last_execution.status + - name + - risk_score + - riskScore + - severity + - updated_at + - updatedAt + type: string + HistoryWindowStart: + $ref: '#/components/schemas/NonEmptyString' + IndexPatternArray: + items: + type: string + type: array + InternalRuleSource: + description: >- + Type of rule source for internally sourced rules, i.e. created within + the Kibana apps. + type: object + properties: + type: + enum: + - internal + type: string + required: + - type + InvestigationFields: + type: object + properties: + field_names: + items: + $ref: '#/components/schemas/NonEmptyString' + minItems: 1 + type: array + required: + - field_names + InvestigationGuide: + description: Notes to help investigate alerts produced by the rule. + type: string + IsExternalRuleCustomized: + description: >- + Determines whether an external/prebuilt rule has been customized by the + user (i.e. any of its fields have been modified and diverged from the + base value). + type: boolean + IsRuleEnabled: + description: Determines whether the rule is enabled. + type: boolean + IsRuleImmutable: + deprecated: true + description: >- + This field determines whether the rule is a prebuilt Elastic rule. It + will be replaced with the `rule_source` field. + type: boolean + ItemsPerSearch: + minimum: 1 + type: integer + KqlQueryLanguage: + enum: + - kuery + - lucene + type: string + MachineLearningJobId: + description: Machine learning job ID + oneOf: + - type: string + - items: + type: string + minItems: 1 + type: array + MachineLearningRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/MachineLearningRuleResponseFields' + MachineLearningRuleCreateFields: + $ref: '#/components/schemas/MachineLearningRuleRequiredFields' + MachineLearningRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/MachineLearningRuleCreateFields' + MachineLearningRulePatchFields: + type: object + properties: + anomaly_threshold: + $ref: '#/components/schemas/AnomalyThreshold' + machine_learning_job_id: + $ref: '#/components/schemas/MachineLearningJobId' + type: + description: Rule type + enum: + - machine_learning + type: string + MachineLearningRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/MachineLearningRulePatchFields' + MachineLearningRuleRequiredFields: + type: object + properties: + anomaly_threshold: + $ref: '#/components/schemas/AnomalyThreshold' + machine_learning_job_id: + $ref: '#/components/schemas/MachineLearningJobId' + type: + description: Rule type + enum: + - machine_learning + type: string + required: + - type + - machine_learning_job_id + - anomaly_threshold + MachineLearningRuleResponseFields: + $ref: '#/components/schemas/MachineLearningRuleRequiredFields' + MachineLearningRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/MachineLearningRuleCreateFields' + MaxSignals: + minimum: 1 + type: integer + NewTermsFields: + items: + type: string + maxItems: 3 + minItems: 1 + type: array + NewTermsRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/NewTermsRuleResponseFields' + NewTermsRuleCreateFields: + allOf: + - $ref: '#/components/schemas/NewTermsRuleRequiredFields' + - $ref: '#/components/schemas/NewTermsRuleOptionalFields' + - $ref: '#/components/schemas/NewTermsRuleDefaultableFields' + NewTermsRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/NewTermsRuleCreateFields' + NewTermsRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + NewTermsRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + NewTermsRulePatchFields: + allOf: + - type: object + properties: + history_window_start: + $ref: '#/components/schemas/HistoryWindowStart' + new_terms_fields: + $ref: '#/components/schemas/NewTermsFields' + query: + $ref: '#/components/schemas/RuleQuery' + type: + description: Rule type + enum: + - new_terms + type: string + - $ref: '#/components/schemas/NewTermsRuleOptionalFields' + - $ref: '#/components/schemas/NewTermsRuleDefaultableFields' + NewTermsRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/NewTermsRulePatchFields' + NewTermsRuleRequiredFields: + type: object + properties: + history_window_start: + $ref: '#/components/schemas/HistoryWindowStart' + new_terms_fields: + $ref: '#/components/schemas/NewTermsFields' + query: + $ref: '#/components/schemas/RuleQuery' + type: + description: Rule type + enum: + - new_terms + type: string + required: + - type + - query + - new_terms_fields + - history_window_start + NewTermsRuleResponseFields: + allOf: + - $ref: '#/components/schemas/NewTermsRuleRequiredFields' + - $ref: '#/components/schemas/NewTermsRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + NewTermsRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/NewTermsRuleCreateFields' + NonEmptyString: + description: A string that is not empty and does not contain only whitespace + minLength: 1 + pattern: ^(?! *$).+$ + type: string + NormalizedRuleAction: + additionalProperties: false + type: object + properties: + alerts_filter: + $ref: '#/components/schemas/RuleActionAlertsFilter' + frequency: + $ref: '#/components/schemas/RuleActionFrequency' + group: + $ref: '#/components/schemas/RuleActionGroup' + id: + $ref: '#/components/schemas/RuleActionId' + params: + $ref: '#/components/schemas/RuleActionParams' + required: + - group + - id + - params + NormalizedRuleError: + type: object + properties: + err_code: + $ref: '#/components/schemas/BulkActionsDryRunErrCode' + message: + type: string + rules: + items: + $ref: '#/components/schemas/RuleDetailsInError' + type: array + status_code: + type: integer + required: + - message + - status_code + - rules + OsqueryParams: + type: object + properties: + ecs_mapping: + $ref: '#/components/schemas/EcsMapping' + pack_id: + type: string + queries: + items: + $ref: '#/components/schemas/OsqueryQuery' + type: array + query: + type: string + saved_query_id: + type: string + timeout: + type: number + OsqueryQuery: + type: object + properties: + ecs_mapping: + $ref: '#/components/schemas/EcsMapping' + id: + description: Query ID + type: string + platform: + type: string + query: + description: Query to execute + type: string + removed: + type: boolean + snapshot: + type: boolean + version: + description: Query version + type: string + required: + - id + - query + OsqueryResponseAction: + type: object + properties: + action_type_id: + enum: + - .osquery + type: string + params: + $ref: '#/components/schemas/OsqueryParams' + required: + - action_type_id + - params + ProcessesParams: + type: object + properties: + command: + enum: + - kill-process + - suspend-process + type: string + comment: + type: string + config: + type: object + properties: + field: + description: Field to use instead of process.pid + type: string + overwrite: + default: true + description: Whether to overwrite field with process.pid + type: boolean + required: + - field + required: + - command + - config + QueryRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/QueryRuleResponseFields' + QueryRuleCreateFields: + allOf: + - $ref: '#/components/schemas/QueryRuleRequiredFields' + - $ref: '#/components/schemas/QueryRuleOptionalFields' + - $ref: '#/components/schemas/QueryRuleDefaultableFields' + QueryRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/QueryRuleCreateFields' + QueryRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + query: + $ref: '#/components/schemas/RuleQuery' + QueryRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + response_actions: + items: + $ref: '#/components/schemas/ResponseAction' + type: array + saved_id: + $ref: '#/components/schemas/SavedQueryId' + QueryRulePatchFields: + allOf: + - type: object + properties: + type: + description: Rule type + enum: + - query + type: string + - $ref: '#/components/schemas/QueryRuleOptionalFields' + - $ref: '#/components/schemas/QueryRuleDefaultableFields' + QueryRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/QueryRulePatchFields' + QueryRuleRequiredFields: + type: object + properties: + type: + description: Rule type + enum: + - query + type: string + required: + - type + QueryRuleResponseFields: + allOf: + - $ref: '#/components/schemas/QueryRuleRequiredFields' + - $ref: '#/components/schemas/QueryRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + query: + $ref: '#/components/schemas/RuleQuery' + required: + - query + - language + QueryRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/QueryRuleCreateFields' + RelatedIntegration: + type: object + properties: + integration: + $ref: '#/components/schemas/NonEmptyString' + package: + $ref: '#/components/schemas/NonEmptyString' + version: + $ref: '#/components/schemas/NonEmptyString' + required: + - package + - version + RelatedIntegrationArray: + items: + $ref: '#/components/schemas/RelatedIntegration' + type: array + RequiredField: + description: Describes an Elasticsearch field that is needed for the rule to function + type: object + properties: + ecs: + description: Whether the field is an ECS field + type: boolean + name: + $ref: '#/components/schemas/NonEmptyString' + description: Name of an Elasticsearch field + type: + $ref: '#/components/schemas/NonEmptyString' + description: Type of the Elasticsearch field + required: + - name + - type + - ecs + RequiredFieldArray: + items: + $ref: '#/components/schemas/RequiredField' + type: array + RequiredFieldInput: + description: >- + Input parameters to create a RequiredField. Does not include the `ecs` + field, because `ecs` is calculated on the backend based on the field + name and type. + type: object + properties: + name: + $ref: '#/components/schemas/NonEmptyString' + description: Name of an Elasticsearch field + type: + $ref: '#/components/schemas/NonEmptyString' + description: Type of an Elasticsearch field + required: + - name + - type + ResponseAction: + oneOf: + - $ref: '#/components/schemas/OsqueryResponseAction' + - $ref: '#/components/schemas/EndpointResponseAction' + ResponseFields: + type: object + properties: + created_at: + format: date-time + type: string + created_by: + type: string + execution_summary: + $ref: '#/components/schemas/RuleExecutionSummary' + id: + $ref: '#/components/schemas/RuleObjectId' + immutable: + $ref: '#/components/schemas/IsRuleImmutable' + required_fields: + $ref: '#/components/schemas/RequiredFieldArray' + revision: + minimum: 0 + type: integer + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_source: + $ref: '#/components/schemas/RuleSource' + updated_at: + format: date-time + type: string + updated_by: + type: string + required: + - id + - rule_id + - immutable + - updated_at + - updated_by + - created_at + - created_by + - revision + - related_integrations + - required_fields + RiskScore: + description: Risk score (0 to 100) + maximum: 100 + minimum: 0 + type: integer + RiskScoreMapping: + description: >- + Overrides generated alerts' risk_score with a value from the source + event + items: + type: object + properties: + field: + type: string + operator: + enum: + - equals + type: string + risk_score: + $ref: '#/components/schemas/RiskScore' + value: + type: string + required: + - field + - operator + - value + type: array + RuleAction: + type: object + properties: + action_type_id: + description: The action type used for sending notifications. + type: string + alerts_filter: + $ref: '#/components/schemas/RuleActionAlertsFilter' + frequency: + $ref: '#/components/schemas/RuleActionFrequency' + group: + $ref: '#/components/schemas/RuleActionGroup' + id: + $ref: '#/components/schemas/RuleActionId' + params: + $ref: '#/components/schemas/RuleActionParams' + uuid: + $ref: '#/components/schemas/NonEmptyString' + required: + - action_type_id + - group + - id + - params + RuleActionAlertsFilter: + additionalProperties: true + type: object + RuleActionFrequency: + description: >- + The action frequency defines when the action runs (for example, only on + rule execution or at specific time intervals). + type: object + properties: + notifyWhen: + $ref: '#/components/schemas/RuleActionNotifyWhen' + summary: + description: >- + Action summary indicates whether we will send a summary notification + about all the generate alerts or notification per individual alert + type: boolean + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + nullable: true + required: + - summary + - notifyWhen + - throttle + RuleActionGroup: + description: >- + Optionally groups actions by use cases. Use `default` for alert + notifications. + type: string + RuleActionId: + description: The connector ID. + type: string + RuleActionNotifyWhen: + description: >- + The condition for throttling the notification: `onActionGroupChange`, + `onActiveAlert`, or `onThrottleInterval` + enum: + - onActiveAlert + - onThrottleInterval + - onActionGroupChange + type: string + RuleActionParams: + additionalProperties: true + description: >- + Object containing the allowed connector fields, which varies according + to the connector type. + type: object + RuleActionThrottle: + description: Defines the interval on which a rule's actions are executed. + oneOf: + - enum: + - no_actions + - rule + type: string + - description: 'Time interval in seconds, minutes, hours, or days.' + example: 1h + pattern: '^[1-9]\d*[smhd]$' + type: string + RuleAuthorArray: + items: + type: string + type: array + RuleCreateProps: + anyOf: + - $ref: '#/components/schemas/EqlRuleCreateProps' + - $ref: '#/components/schemas/QueryRuleCreateProps' + - $ref: '#/components/schemas/SavedQueryRuleCreateProps' + - $ref: '#/components/schemas/ThresholdRuleCreateProps' + - $ref: '#/components/schemas/ThreatMatchRuleCreateProps' + - $ref: '#/components/schemas/MachineLearningRuleCreateProps' + - $ref: '#/components/schemas/NewTermsRuleCreateProps' + - $ref: '#/components/schemas/EsqlRuleCreateProps' + discriminator: + propertyName: type + RuleDescription: + minLength: 1 + type: string + RuleDetailsInError: + type: object + properties: + id: + type: string + name: + type: string + required: + - id + RuleExceptionList: + type: object + properties: + id: + $ref: '#/components/schemas/NonEmptyString' + description: ID of the exception container + list_id: + $ref: '#/components/schemas/NonEmptyString' + description: List ID of the exception container + namespace_type: + description: Determines the exceptions validity in rule's Kibana space + enum: + - agnostic + - single + type: string + type: + $ref: '#/components/schemas/ExceptionListType' + required: + - id + - list_id + - type + - namespace_type + RuleExecutionMetrics: + type: object + properties: + execution_gap_duration_s: + description: Duration in seconds of execution gap + minimum: 0 + type: integer + total_enrichment_duration_ms: + description: >- + Total time spent enriching documents during current rule execution + cycle + minimum: 0 + type: integer + total_indexing_duration_ms: + description: >- + Total time spent indexing documents during current rule execution + cycle + minimum: 0 + type: integer + total_search_duration_ms: + description: >- + Total time spent performing ES searches as measured by Kibana; + includes network latency and time spent serializing/deserializing + request/response + minimum: 0 + type: integer + RuleExecutionStatus: + description: >- + Custom execution status of Security rules that is different from the + status used in the Alerting Framework. We merge our custom status with + the Framework's status to determine the resulting status of a rule. + + - going to run - @deprecated Replaced by the 'running' status but left + for backwards compatibility with rule execution events already written + to Event Log in the prior versions of Kibana. Don't use when writing + rule status changes. + + - running - Rule execution started but not reached any intermediate or + final status. + + - partial failure - Rule can partially fail for various reasons either + in the middle of an execution (in this case we update its status right + away) or in the end of it. So currently this status can be both + intermediate and final at the same time. A typical reason for a partial + failure: not all the indices that the rule searches over actually exist. + + - failed - Rule failed to execute due to unhandled exception or a reason + defined in the business logic of its executor function. + + - succeeded - Rule executed successfully without any issues. Note: this + status is just an indication of a rule's "health". The rule might or + might not generate any alerts despite of it. + enum: + - going to run + - running + - partial failure + - failed + - succeeded + type: string + RuleExecutionStatusOrder: + type: integer + RuleExecutionSummary: + type: object + properties: + last_execution: + type: object + properties: + date: + description: Date of the last execution + format: date-time + type: string + message: + type: string + metrics: + $ref: '#/components/schemas/RuleExecutionMetrics' + status: + $ref: '#/components/schemas/RuleExecutionStatus' + description: Status of the last execution + status_order: + $ref: '#/components/schemas/RuleExecutionStatusOrder' + required: + - date + - status + - status_order + - message + - metrics + required: + - last_execution + RuleFalsePositiveArray: + items: + type: string + type: array + RuleFilterArray: + items: {} + type: array + RuleInterval: + description: >- + Frequency of rule execution, using a date math range. For example, "1h" + means the rule runs every hour. Defaults to 5m (5 minutes). + type: string + RuleIntervalFrom: + description: >- + Time from which data is analyzed each time the rule executes, using a + date math range. For example, now-4200s means the rule analyzes data + from 70 minutes before its start time. Defaults to now-6m (analyzes data + from 6 minutes before the start time). + format: date-math + type: string + RuleIntervalTo: + type: string + RuleLicense: + description: The rule's license. + type: string + RuleMetadata: + additionalProperties: true + type: object + RuleName: + minLength: 1 + type: string + RuleNameOverride: + description: Sets the source field for the alert's signal.rule.name value + type: string + RuleObjectId: + $ref: '#/components/schemas/UUID' + RulePatchProps: + anyOf: + - $ref: '#/components/schemas/EqlRulePatchProps' + - $ref: '#/components/schemas/QueryRulePatchProps' + - $ref: '#/components/schemas/SavedQueryRulePatchProps' + - $ref: '#/components/schemas/ThresholdRulePatchProps' + - $ref: '#/components/schemas/ThreatMatchRulePatchProps' + - $ref: '#/components/schemas/MachineLearningRulePatchProps' + - $ref: '#/components/schemas/NewTermsRulePatchProps' + - $ref: '#/components/schemas/EsqlRulePatchProps' + RuleQuery: + type: string + RuleReferenceArray: + items: + type: string + type: array + RuleResponse: + anyOf: + - $ref: '#/components/schemas/EqlRule' + - $ref: '#/components/schemas/QueryRule' + - $ref: '#/components/schemas/SavedQueryRule' + - $ref: '#/components/schemas/ThresholdRule' + - $ref: '#/components/schemas/ThreatMatchRule' + - $ref: '#/components/schemas/MachineLearningRule' + - $ref: '#/components/schemas/NewTermsRule' + - $ref: '#/components/schemas/EsqlRule' + discriminator: + propertyName: type + RuleSignatureId: + description: 'Could be any string, not necessarily a UUID' + type: string + RuleSource: + description: >- + Discriminated union that determines whether the rule is internally + sourced (created within the Kibana app) or has an external source, such + as the Elastic Prebuilt rules repo. + discriminator: + propertyName: type + oneOf: + - $ref: '#/components/schemas/ExternalRuleSource' + - $ref: '#/components/schemas/InternalRuleSource' + RuleTagArray: + description: >- + String array containing words and phrases to help categorize, filter, + and search rules. Defaults to an empty array. + items: + type: string + type: array + RuleUpdateProps: + anyOf: + - $ref: '#/components/schemas/EqlRuleUpdateProps' + - $ref: '#/components/schemas/QueryRuleUpdateProps' + - $ref: '#/components/schemas/SavedQueryRuleUpdateProps' + - $ref: '#/components/schemas/ThresholdRuleUpdateProps' + - $ref: '#/components/schemas/ThreatMatchRuleUpdateProps' + - $ref: '#/components/schemas/MachineLearningRuleUpdateProps' + - $ref: '#/components/schemas/NewTermsRuleUpdateProps' + - $ref: '#/components/schemas/EsqlRuleUpdateProps' + discriminator: + propertyName: type + RuleVersion: + description: The rule's version number. + minimum: 1 + type: integer + SavedObjectResolveAliasPurpose: + enum: + - savedObjectConversion + - savedObjectImport + type: string + SavedObjectResolveAliasTargetId: + type: string + SavedObjectResolveOutcome: + enum: + - exactMatch + - aliasMatch + - conflict + type: string + SavedQueryId: + type: string + SavedQueryRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/SavedQueryRuleResponseFields' + SavedQueryRuleCreateFields: + allOf: + - $ref: '#/components/schemas/SavedQueryRuleRequiredFields' + - $ref: '#/components/schemas/SavedQueryRuleOptionalFields' + - $ref: '#/components/schemas/SavedQueryRuleDefaultableFields' + SavedQueryRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/SavedQueryRuleCreateFields' + SavedQueryRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + SavedQueryRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + query: + $ref: '#/components/schemas/RuleQuery' + response_actions: + items: + $ref: '#/components/schemas/ResponseAction' + type: array + SavedQueryRulePatchFields: + allOf: + - type: object + properties: + saved_id: + $ref: '#/components/schemas/SavedQueryId' + type: + description: Rule type + enum: + - saved_query + type: string + - $ref: '#/components/schemas/SavedQueryRuleOptionalFields' + - $ref: '#/components/schemas/SavedQueryRuleDefaultableFields' + SavedQueryRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/SavedQueryRulePatchFields' + SavedQueryRuleRequiredFields: + type: object + properties: + saved_id: + $ref: '#/components/schemas/SavedQueryId' + type: + description: Rule type + enum: + - saved_query + type: string + required: + - type + - saved_id + SavedQueryRuleResponseFields: + allOf: + - $ref: '#/components/schemas/SavedQueryRuleRequiredFields' + - $ref: '#/components/schemas/SavedQueryRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + SavedQueryRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/SavedQueryRuleCreateFields' + SetupGuide: + type: string + Severity: + description: Severity of the rule + enum: + - low + - medium + - high + - critical + type: string + SeverityMapping: + description: Overrides generated alerts' severity with values from the source event + items: + type: object + properties: + field: + type: string + operator: + enum: + - equals + type: string + severity: + $ref: '#/components/schemas/Severity' + value: + type: string + required: + - field + - operator + - severity + - value + type: array + SortOrder: + enum: + - asc + - desc + type: string + Threat: + type: object + properties: + framework: + description: Relevant attack framework + type: string + tactic: + $ref: '#/components/schemas/ThreatTactic' + technique: + description: Array containing information on the attack techniques (optional) + items: + $ref: '#/components/schemas/ThreatTechnique' + type: array + required: + - framework + - tactic + ThreatArray: + items: + $ref: '#/components/schemas/Threat' + type: array + ThreatFilters: + items: + description: >- + Query and filter context array used to filter documents from the + Elasticsearch index containing the threat values + type: array + ThreatIndex: + items: + type: string + type: array + ThreatIndicatorPath: + description: >- + Defines the path to the threat indicator in the indicator documents + (optional) + type: string + ThreatMapping: + items: + type: object + properties: + entries: + items: + type: object + properties: + field: + $ref: '#/components/schemas/NonEmptyString' + type: + enum: + - mapping + type: string + value: + $ref: '#/components/schemas/NonEmptyString' + required: + - field + - type + - value + type: array + required: + - entries + minItems: 1 + type: array + ThreatMatchRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/ThreatMatchRuleResponseFields' + ThreatMatchRuleCreateFields: + allOf: + - $ref: '#/components/schemas/ThreatMatchRuleRequiredFields' + - $ref: '#/components/schemas/ThreatMatchRuleOptionalFields' + - $ref: '#/components/schemas/ThreatMatchRuleDefaultableFields' + ThreatMatchRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThreatMatchRuleCreateFields' + ThreatMatchRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + ThreatMatchRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/AlertSuppression' + concurrent_searches: + $ref: '#/components/schemas/ConcurrentSearches' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + items_per_search: + $ref: '#/components/schemas/ItemsPerSearch' + saved_id: + $ref: '#/components/schemas/SavedQueryId' + threat_filters: + $ref: '#/components/schemas/ThreatFilters' + threat_indicator_path: + $ref: '#/components/schemas/ThreatIndicatorPath' + threat_language: + $ref: '#/components/schemas/KqlQueryLanguage' + ThreatMatchRulePatchFields: + allOf: + - type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threat_index: + $ref: '#/components/schemas/ThreatIndex' + threat_mapping: + $ref: '#/components/schemas/ThreatMapping' + threat_query: + $ref: '#/components/schemas/ThreatQuery' + type: + description: Rule type + enum: + - threat_match + type: string + - $ref: '#/components/schemas/ThreatMatchRuleOptionalFields' + - $ref: '#/components/schemas/ThreatMatchRuleDefaultableFields' + ThreatMatchRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/ThreatMatchRulePatchFields' + ThreatMatchRuleRequiredFields: + type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threat_index: + $ref: '#/components/schemas/ThreatIndex' + threat_mapping: + $ref: '#/components/schemas/ThreatMapping' + threat_query: + $ref: '#/components/schemas/ThreatQuery' + type: + description: Rule type + enum: + - threat_match + type: string + required: + - type + - query + - threat_query + - threat_mapping + - threat_index + ThreatMatchRuleResponseFields: + allOf: + - $ref: '#/components/schemas/ThreatMatchRuleRequiredFields' + - $ref: '#/components/schemas/ThreatMatchRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + ThreatMatchRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThreatMatchRuleCreateFields' + ThreatQuery: + description: Query to execute + type: string + ThreatSubtechnique: + type: object + properties: + id: + description: Subtechnique ID + type: string + name: + description: Subtechnique name + type: string + reference: + description: Subtechnique reference + type: string + required: + - id + - name + - reference + ThreatTactic: + type: object + properties: + id: + description: Tactic ID + type: string + name: + description: Tactic name + type: string + reference: + description: Tactic reference + type: string + required: + - id + - name + - reference + ThreatTechnique: + type: object + properties: + id: + description: Technique ID + type: string + name: + description: Technique name + type: string + reference: + description: Technique reference + type: string + subtechnique: + description: Array containing more specific information on the attack technique + items: + $ref: '#/components/schemas/ThreatSubtechnique' + type: array + required: + - id + - name + - reference + Threshold: + type: object + properties: + cardinality: + $ref: '#/components/schemas/ThresholdCardinality' + field: + $ref: '#/components/schemas/ThresholdField' + value: + $ref: '#/components/schemas/ThresholdValue' + required: + - field + - value + ThresholdAlertSuppression: + type: object + properties: + duration: + $ref: '#/components/schemas/AlertSuppressionDuration' + required: + - duration + ThresholdCardinality: + items: + type: object + properties: + field: + type: string + value: + minimum: 0 + type: integer + required: + - field + - value + type: array + ThresholdField: + description: Field to aggregate on + oneOf: + - type: string + - items: + type: string + type: array + ThresholdRule: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - version + - tags + - enabled + - risk_score_mapping + - severity_mapping + - interval + - from + - to + - actions + - exceptions_list + - author + - false_positives + - references + - max_signals + - threat + - setup + - related_integrations + - required_fields + - $ref: '#/components/schemas/ResponseFields' + - $ref: '#/components/schemas/ThresholdRuleResponseFields' + ThresholdRuleCreateFields: + allOf: + - $ref: '#/components/schemas/ThresholdRuleRequiredFields' + - $ref: '#/components/schemas/ThresholdRuleOptionalFields' + - $ref: '#/components/schemas/ThresholdRuleDefaultableFields' + ThresholdRuleCreateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThresholdRuleCreateFields' + ThresholdRuleDefaultableFields: + type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + ThresholdRuleOptionalFields: + type: object + properties: + alert_suppression: + $ref: '#/components/schemas/ThresholdAlertSuppression' + data_view_id: + $ref: '#/components/schemas/DataViewId' + filters: + $ref: '#/components/schemas/RuleFilterArray' + index: + $ref: '#/components/schemas/IndexPatternArray' + saved_id: + $ref: '#/components/schemas/SavedQueryId' + ThresholdRulePatchFields: + allOf: + - type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threshold: + $ref: '#/components/schemas/Threshold' + type: + description: Rule type + enum: + - threshold + type: string + - $ref: '#/components/schemas/ThresholdRuleOptionalFields' + - $ref: '#/components/schemas/ThresholdRuleDefaultableFields' + ThresholdRulePatchProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + - $ref: '#/components/schemas/ThresholdRulePatchFields' + ThresholdRuleRequiredFields: + type: object + properties: + query: + $ref: '#/components/schemas/RuleQuery' + threshold: + $ref: '#/components/schemas/Threshold' + type: + description: Rule type + enum: + - threshold + type: string + required: + - type + - query + - threshold + ThresholdRuleResponseFields: + allOf: + - $ref: '#/components/schemas/ThresholdRuleRequiredFields' + - $ref: '#/components/schemas/ThresholdRuleOptionalFields' + - type: object + properties: + language: + $ref: '#/components/schemas/KqlQueryLanguage' + required: + - language + ThresholdRuleUpdateProps: + allOf: + - type: object + properties: + actions: + items: + $ref: '#/components/schemas/RuleAction' + type: array + alias_purpose: + $ref: '#/components/schemas/SavedObjectResolveAliasPurpose' + alias_target_id: + $ref: '#/components/schemas/SavedObjectResolveAliasTargetId' + author: + $ref: '#/components/schemas/RuleAuthorArray' + building_block_type: + $ref: '#/components/schemas/BuildingBlockType' + description: + $ref: '#/components/schemas/RuleDescription' + enabled: + $ref: '#/components/schemas/IsRuleEnabled' + exceptions_list: + items: + $ref: '#/components/schemas/RuleExceptionList' + type: array + false_positives: + $ref: '#/components/schemas/RuleFalsePositiveArray' + from: + $ref: '#/components/schemas/RuleIntervalFrom' + id: + $ref: '#/components/schemas/RuleObjectId' + interval: + $ref: '#/components/schemas/RuleInterval' + investigation_fields: + $ref: '#/components/schemas/InvestigationFields' + license: + $ref: '#/components/schemas/RuleLicense' + max_signals: + $ref: '#/components/schemas/MaxSignals' + meta: + $ref: '#/components/schemas/RuleMetadata' + name: + $ref: '#/components/schemas/RuleName' + namespace: + $ref: '#/components/schemas/AlertsIndexNamespace' + note: + $ref: '#/components/schemas/InvestigationGuide' + outcome: + $ref: '#/components/schemas/SavedObjectResolveOutcome' + output_index: + $ref: '#/components/schemas/AlertsIndex' + references: + $ref: '#/components/schemas/RuleReferenceArray' + related_integrations: + $ref: '#/components/schemas/RelatedIntegrationArray' + required_fields: + items: + $ref: '#/components/schemas/RequiredFieldInput' + type: array + risk_score: + $ref: '#/components/schemas/RiskScore' + risk_score_mapping: + $ref: '#/components/schemas/RiskScoreMapping' + rule_id: + $ref: '#/components/schemas/RuleSignatureId' + rule_name_override: + $ref: '#/components/schemas/RuleNameOverride' + setup: + $ref: '#/components/schemas/SetupGuide' + severity: + $ref: '#/components/schemas/Severity' + severity_mapping: + $ref: '#/components/schemas/SeverityMapping' + tags: + $ref: '#/components/schemas/RuleTagArray' + threat: + $ref: '#/components/schemas/ThreatArray' + throttle: + $ref: '#/components/schemas/RuleActionThrottle' + timeline_id: + $ref: '#/components/schemas/TimelineTemplateId' + timeline_title: + $ref: '#/components/schemas/TimelineTemplateTitle' + timestamp_override: + $ref: '#/components/schemas/TimestampOverride' + timestamp_override_fallback_disabled: + $ref: '#/components/schemas/TimestampOverrideFallbackDisabled' + to: + $ref: '#/components/schemas/RuleIntervalTo' + version: + $ref: '#/components/schemas/RuleVersion' + required: + - name + - description + - risk_score + - severity + - $ref: '#/components/schemas/ThresholdRuleCreateFields' + ThresholdValue: + description: Threshold value + minimum: 1 + type: integer + ThrottleForBulkActions: + description: >- + The condition for throttling the notification: 'rule', 'no_actions', or + time duration + enum: + - rule + - 1h + - 1d + - 7d + type: string + TiebreakerField: + description: Sets a secondary field for sorting events + type: string + TimelineTemplateId: + description: Timeline template ID + type: string + TimelineTemplateTitle: + description: Timeline template title + type: string + TimestampField: + description: Contains the event timestamp used for sorting a sequence of events + type: string + TimestampOverride: + description: Sets the time field used to query indices + type: string + TimestampOverrideFallbackDisabled: + description: Disables the fallback to the event's @timestamp field + type: boolean + UUID: + description: A universally unique identifier + format: uuid + type: string + WarningSchema: + type: object + properties: + actionPath: + type: string + buttonLabel: + type: string + message: + type: string + type: + type: string + required: + - type + - message + - actionPath + securitySchemes: + BasicAuth: + scheme: basic + type: http +security: + - BasicAuth: [] diff --git a/x-pack/plugins/security_solution/scripts/openapi/bundle.js b/x-pack/plugins/security_solution/scripts/openapi/bundle.js index cba548cfd2903..e2df0d47f5b47 100644 --- a/x-pack/plugins/security_solution/scripts/openapi/bundle.js +++ b/x-pack/plugins/security_solution/scripts/openapi/bundle.js @@ -9,26 +9,36 @@ require('../../../../../src/setup_node_env'); const { bundle } = require('@kbn/openapi-bundler'); const { join, resolve } = require('path'); -const SECURITY_SOLUTION_ROOT = resolve(__dirname, '../..'); +const ROOT = resolve(__dirname, '../..'); bundle({ - sourceGlob: join(SECURITY_SOLUTION_ROOT, 'common/api/**/*.schema.yaml'), + sourceGlob: join(ROOT, 'common/api/detection_engine/**/*.schema.yaml'), outputFilePath: join( - SECURITY_SOLUTION_ROOT, - 'target/openapi/serverless/security_solution-{version}.bundled.schema.yaml' + ROOT, + 'docs/openapi/serverless/security_solution_detections_api_{version}.bundled.schema.yaml' ), options: { includeLabels: ['serverless'], + specInfo: { + title: 'Security Solution Detections API (Elastic Cloud Serverless)', + description: + 'You can create rules that automatically turn events and external alerts sent to Elastic Security into detection alerts. These alerts are displayed on the Detections page.', + }, }, }); bundle({ - sourceGlob: join(SECURITY_SOLUTION_ROOT, 'common/api/**/*.schema.yaml'), + sourceGlob: join(ROOT, 'common/api/detection_engine/**/*.schema.yaml'), outputFilePath: join( - SECURITY_SOLUTION_ROOT, - 'target/openapi/ess/security_solution-{version}.bundled.schema.yaml' + ROOT, + 'docs/openapi/ess/security_solution_detections_api_{version}.bundled.schema.yaml' ), options: { includeLabels: ['ess'], + specInfo: { + title: 'Security Solution Detections API (Elastic Cloud and self-hosted)', + description: + 'You can create rules that automatically turn events and external alerts sent to Elastic Security into detection alerts. These alerts are displayed on the Detections page.', + }, }, }); diff --git a/x-pack/plugins/security_solution/scripts/openapi/generate.js b/x-pack/plugins/security_solution/scripts/openapi/generate.js index d4484c1f71461..38eb0fe06f95a 100644 --- a/x-pack/plugins/security_solution/scripts/openapi/generate.js +++ b/x-pack/plugins/security_solution/scripts/openapi/generate.js @@ -16,7 +16,7 @@ const SECURITY_SOLUTION_ROOT = resolve(__dirname, '../..'); await generate({ title: 'API route schemas', rootDir: SECURITY_SOLUTION_ROOT, - sourceGlob: './**/*.schema.yaml', + sourceGlob: './common/**/*.schema.yaml', templateName: 'zod_operation_schema', skipLinting: true, }); @@ -24,7 +24,7 @@ const SECURITY_SOLUTION_ROOT = resolve(__dirname, '../..'); await generate({ title: 'API client for tests', rootDir: SECURITY_SOLUTION_ROOT, - sourceGlob: './**/*.schema.yaml', + sourceGlob: './common/**/*.schema.yaml', templateName: 'api_client_supertest', skipLinting: true, bundle: { From d2325ce927b97c5153b7955bbc33c233f68e88c0 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 18 Jun 2024 21:39:32 +0100 Subject: [PATCH 082/127] skip flaky suite (#186315) --- .../pages/cis_integrations/kspm/cis_integration_eks.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts index db0778831964f..3d115fd33f8bf 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts @@ -50,7 +50,8 @@ export default function (providerContext: FtrProviderContext) { }); }); - describe('KSPM EKS Direct Access', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/186315 + describe.skip('KSPM EKS Direct Access', async () => { it('KSPM EKS Direct Access Workflow', async () => { const directAccessKeyId = 'directAccessKeyIdTest'; const directAccessSecretKey = 'directAccessSecretKeyTest'; From 141044e51ec77ea7c5e68c9311a381aecb515497 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:35:24 +0200 Subject: [PATCH 083/127] [Search] Fix search index rerendering unnecessarily (#186412) ## Summary This fixes the search index rerendering on every change, even if nothing actually changed. --- .../components/search_index/search_index.tsx | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx index 09e6b494f94e4..7c13a3f524ccf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useEffect } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { useParams } from 'react-router-dom'; @@ -15,12 +15,15 @@ import { EuiTabbedContent, EuiTabbedContentTab } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { ClientConfigType } from '../../../../../common/types'; + import { generateEncodedPath } from '../../../shared/encode_path_params'; import { ErrorStatePrompt } from '../../../shared/error_state'; import { HttpLogic } from '../../../shared/http'; import { KibanaLogic } from '../../../shared/kibana'; import { SEARCH_INDEX_PATH, SEARCH_INDEX_TAB_PATH } from '../../routes'; +import { ElasticsearchViewIndex } from '../../types'; import { isConnectorIndex, isCrawlerIndex } from '../../utils/indices'; import { ConnectorConfiguration } from '../connector_detail/connector_configuration'; import { EnterpriseSearchContentPageTemplate } from '../layout/page_template'; @@ -223,20 +226,6 @@ export const SearchIndex: React.FC = () => { ...(hasDefaultIngestPipeline ? [PIPELINES_TAB] : []), ]; - const selectedTab = tabs.find((tab) => tab.id === tabId); - - const onTabClick = (tab: EuiTabbedContentTab) => { - KibanaLogic.values.navigateToUrl( - generateEncodedPath( - tab.id === SearchIndexTabId.OVERVIEW ? SEARCH_INDEX_PATH : SEARCH_INDEX_TAB_PATH, - { - indexName, - tabId: tab.id, - } - ) - ); - }; - return ( { rightSideItems: getHeaderActions(index), }} > - {isCrawlerIndex(index) && !index.connector ? ( - - ) : isCrawlerIndex(index) && (Boolean(errorConnectingMessage) || !config.host) ? ( - - ) : ( - <> - {indexName === index?.name && ( - - )} - {isCrawlerIndex(index) && } - - )} + ); }; + +interface ContentProps { + config?: ClientConfigType; + errorConnectingMessage: string; + index?: ElasticsearchViewIndex; + tabId?: string; + tabs: EuiTabbedContentTab[]; +} + +const Content: React.FC = ({ + config, + errorConnectingMessage, + index, + tabs, + tabId, +}) => { + const selectedTab = useMemo(() => tabs.find((tab) => tab.id === tabId), [tabId]); + + const onTabClick = (tab: EuiTabbedContentTab) => { + KibanaLogic.values.navigateToUrl( + generateEncodedPath( + tab.id === SearchIndexTabId.OVERVIEW ? SEARCH_INDEX_PATH : SEARCH_INDEX_TAB_PATH, + { + indexName: index?.name || '', + tabId: tab.id, + } + ) + ); + }; + + if (isCrawlerIndex(index) && !index.connector) { + return ; + } + if (isCrawlerIndex(index) && (Boolean(errorConnectingMessage) || !config?.host)) { + return ; + } + return ( + <> + + {isCrawlerIndex(index) && } + + ); +}; From 0dd4f9b8c76f467b8e327b64d70b43560a9f8642 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 19 Jun 2024 00:13:13 +0200 Subject: [PATCH 084/127] Un-revert "Siem query rule - reduce field_caps usage" (#186317) ## Summary https://github.com/elastic/kibana/pull/184890 was reverted in https://github.com/elastic/kibana/pull/186196 because it contained a bug with alerts created using Lucene queries. The bug was fixed in https://github.com/elastic/kibana/pull/186217. This PR un-reverts the original changes and preserves the fix. It also adds unit tests to cover the failed cases. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../data/common/search/search_source/index.ts | 1 + .../search_source/query_to_fields.test.ts | 82 +++++++++++++++++++ .../search/search_source/query_to_fields.ts | 58 +++++++++++++ .../search/search_source/search_source.ts | 41 +--------- .../rule_types/__mocks__/rule_type.ts | 8 ++ .../create_security_rule_type_wrapper.ts | 9 +- .../rule_types/query/query.ts | 1 + .../rule_types/utils/get_filter.ts | 8 +- .../utils/get_query_filter_load_fields.ts | 67 +++++++++++++++ 9 files changed, 234 insertions(+), 41 deletions(-) create mode 100644 src/plugins/data/common/search/search_source/query_to_fields.test.ts create mode 100644 src/plugins/data/common/search/search_source/query_to_fields.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter_load_fields.ts diff --git a/src/plugins/data/common/search/search_source/index.ts b/src/plugins/data/common/search/search_source/index.ts index 189538415ab53..0bc25a0fe85d0 100644 --- a/src/plugins/data/common/search/search_source/index.ts +++ b/src/plugins/data/common/search/search_source/index.ts @@ -15,3 +15,4 @@ export * from './fetch'; export * from './search_source'; export * from './search_source_service'; export * from './types'; +export * from './query_to_fields'; diff --git a/src/plugins/data/common/search/search_source/query_to_fields.test.ts b/src/plugins/data/common/search/search_source/query_to_fields.test.ts new file mode 100644 index 0000000000000..b7ed2f6f12333 --- /dev/null +++ b/src/plugins/data/common/search/search_source/query_to_fields.test.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 { EsQuerySortValue, queryToFields, SearchRequest, SortDirection } from '../..'; +import { DataViewLazy } from '@kbn/data-views-plugin/common'; + +describe('SearchSource#queryToFields', () => { + it('should include time field', async () => { + const dataView = { + timeFieldName: '@timestamp', + getSourceFiltering: jest.fn(), + getFields: jest.fn().mockResolvedValue({ + getFieldMapSorted: jest.fn(), + }), + }; + const request: SearchRequest = { query: [] }; + await queryToFields({ dataView: dataView as unknown as DataViewLazy, request }); + const { fieldName } = dataView.getFields.mock.calls[0][0]; + expect(fieldName).toEqual(['@timestamp']); + }); + + it('should include sort field', async () => { + const dataView = { + getSourceFiltering: jest.fn(), + getFields: jest.fn().mockResolvedValue({ + getFieldMapSorted: jest.fn(), + }), + }; + const sort: EsQuerySortValue = { bytes: SortDirection.asc }; + const request: SearchRequest = { query: [] }; + await queryToFields({ dataView: dataView as unknown as DataViewLazy, sort, request }); + const { fieldName } = dataView.getFields.mock.calls[0][0]; + expect(fieldName).toEqual(['bytes']); + }); + + it('should include request KQL query fields', async () => { + const dataView = { + timeFieldName: '@timestamp', + getSourceFiltering: jest.fn(), + getFields: jest.fn().mockResolvedValue({ + getFieldMapSorted: jest.fn(), + }), + }; + const request: SearchRequest = { + query: [ + { + language: 'kuery', + query: 'log.level: debug AND NOT message: unknown', + }, + ], + }; + await queryToFields({ dataView: dataView as unknown as DataViewLazy, request }); + const { fieldName } = dataView.getFields.mock.calls[0][0]; + expect(fieldName).toEqual(['@timestamp', 'log.level', 'message']); + }); + + it('should not include request Lucene query fields', async () => { + const dataView = { + timeFieldName: '@timestamp', + getSourceFiltering: jest.fn(), + getFields: jest.fn().mockResolvedValue({ + getFieldMapSorted: jest.fn(), + }), + }; + const request: SearchRequest = { + query: [ + { + language: 'lucene', + query: 'host: artifacts\\.*', + }, + ], + }; + await queryToFields({ dataView: dataView as unknown as DataViewLazy, request }); + const { fieldName } = dataView.getFields.mock.calls[0][0]; + expect(fieldName).toEqual(['@timestamp']); + }); +}); diff --git a/src/plugins/data/common/search/search_source/query_to_fields.ts b/src/plugins/data/common/search/search_source/query_to_fields.ts new file mode 100644 index 0000000000000..ebae3354dcea9 --- /dev/null +++ b/src/plugins/data/common/search/search_source/query_to_fields.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 { DataViewLazy } from '@kbn/data-views-plugin/common'; +import { fromKueryExpression, getKqlFieldNames } from '@kbn/es-query'; +import type { SearchRequest } from './fetch'; +import { EsQuerySortValue } from '../..'; + +export async function queryToFields({ + dataView, + sort, + request, +}: { + dataView: DataViewLazy; + sort?: EsQuerySortValue | EsQuerySortValue[]; + request: SearchRequest; +}) { + let fields = dataView.timeFieldName ? [dataView.timeFieldName] : []; + if (sort) { + const sortArr = Array.isArray(sort) ? sort : [sort]; + fields.push(...sortArr.flatMap((s) => Object.keys(s))); + } + for (const query of request.query) { + if (query.query && query.language === 'kuery') { + const nodes = fromKueryExpression(query.query); + const queryFields = getKqlFieldNames(nodes); + fields = fields.concat(queryFields); + } + } + const filters = request.filters; + if (filters) { + const filtersArr = Array.isArray(filters) ? filters : [filters]; + for (const f of filtersArr) { + // unified search bar filters have meta object and key (regular filters) + // unified search bar "custom" filters ("Edit as query DSL", where meta.key is not present but meta is) + // Any other Elasticsearch query DSL filter that gets passed in by consumers (not coming from unified search, and these probably won't have a meta key at all) + if (f?.meta?.key && f.meta.disabled !== true) { + fields.push(f.meta.key); + } + } + } + + // if source filtering is enabled, we need to fetch all the fields + const fieldName = + dataView.getSourceFiltering() && dataView.getSourceFiltering().excludes.length ? ['*'] : fields; + + if (fieldName.length) { + return (await dataView.getFields({ fieldName })).getFieldMapSorted(); + } + + // no fields needed to be loaded for query + return {}; +} diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index 0989251a3b50c..a5009f350bd3a 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -77,11 +77,9 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { buildEsQuery, Filter, - fromKueryExpression, isOfQueryType, isPhraseFilter, isPhrasesFilter, - getKqlFieldNames, } from '@kbn/es-query'; import { fieldWildcardFilter } from '@kbn/kibana-utils-plugin/common'; import { getHighlightRequest } from '@kbn/field-formats-plugin/common'; @@ -95,6 +93,7 @@ import type { ISearchGeneric, IKibanaSearchResponse, IEsSearchResponse } from '@ import { normalizeSortRequest } from './normalize_sort_request'; import { AggConfigSerialized, DataViewField, SerializedSearchSourceFields } from '../..'; +import { queryToFields } from './query_to_fields'; import { AggConfigs, EsQuerySortValue } from '../..'; import type { @@ -778,43 +777,7 @@ export class SearchSource { public async loadDataViewFields(dataView: DataViewLazy) { const request = this.mergeProps(this, { body: {} }); - let fields = dataView.timeFieldName ? [dataView.timeFieldName] : []; - const sort = this.getField('sort'); - if (sort) { - const sortArr = Array.isArray(sort) ? sort : [sort]; - for (const s of sortArr) { - const keys = Object.keys(s); - fields = fields.concat(keys); - } - } - for (const query of request.query) { - if (query.query && query.language === 'kuery') { - const nodes = fromKueryExpression(query.query); - const queryFields = getKqlFieldNames(nodes); - fields = fields.concat(queryFields); - } - } - const filters = request.filters; - if (filters) { - const filtersArr = Array.isArray(filters) ? filters : [filters]; - for (const f of filtersArr) { - fields = fields.concat(f.meta.key); - } - } - fields = fields.filter((f) => Boolean(f)); - - if (dataView.getSourceFiltering() && dataView.getSourceFiltering().excludes.length) { - // if source filtering is enabled, we need to fetch all the fields - return (await dataView.getFields({ fieldName: ['*'] })).getFieldMapSorted(); - } else if (fields.length) { - return ( - await dataView.getFields({ - fieldName: fields, - }) - ).getFieldMapSorted(); - } - // no fields needed to be loaded for query - return {}; + return await queryToFields({ dataView, request }); } private flatten() { 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 6a863728cd746..6cf237ca583e2 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 @@ -104,6 +104,14 @@ export const createRuleTypeMocks = ( alertWithPersistence: jest.fn(), logger: loggerMock, shouldWriteAlerts: () => true, + dataViews: { + createDataViewLazy: jest.fn().mockResolvedValue({ + getFields: jest.fn().mockResolvedValue({ + getFieldMapSorted: jest.fn().mockReturnValue({}), + }), + getSourceFiltering: jest.fn().mockReturnValue({ excludes: [] }), + }), + }, }; return { 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 72caa1d61ff63..471087fa77a4a 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 @@ -26,6 +26,8 @@ import { hasTimestampFields, isMachineLearningParams, isEsqlParams, + isQueryParams, + isEqlParams, getDisabledActionsWarningText, } from './utils/utils'; import { DEFAULT_MAX_SIGNALS, DEFAULT_SEARCH_AFTER_PAGE_SIZE } from '../../../../common/constants'; @@ -341,7 +343,12 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = }); } - if (!isMachineLearningParams(params) && !isEsqlParams(params)) { + if ( + !isMachineLearningParams(params) && + !isEsqlParams(params) && + !isQueryParams(params) && + !isEqlParams(params) + ) { inputIndexFields = await getFieldsForWildcard({ index: inputIndex, dataViews: services.dataViews, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts index b3de5a39d829f..272184dbf1e58 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts @@ -59,6 +59,7 @@ export const queryExecutor = async ({ index: runOpts.inputIndex, exceptionFilter: runOpts.exceptionFilter, fields: runOpts.inputIndexFields, + loadFields: true, }); const license = await firstValueFrom(licensing.license$); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts index 7d7492bd17e2b..920e2c2df9c5e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_filter.ts @@ -26,7 +26,8 @@ import type { SavedIdOrUndefined } from '../../../../../common/api/detection_eng 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'; +import { getQueryFilter as getQueryFilterNoLoadFields } from './get_query_filter'; +import { getQueryFilterLoadFields } from './get_query_filter_load_fields'; export interface GetFilterArgs { type: Type; @@ -38,6 +39,7 @@ export interface GetFilterArgs { index: IndexPatternArray | undefined; exceptionFilter: Filter | undefined; fields?: DataViewFieldBase[]; + loadFields?: boolean; } interface QueryAttributes { @@ -59,7 +61,11 @@ export const getFilter = async ({ query, exceptionFilter, fields = [], + loadFields = false, }: GetFilterArgs): Promise => { + const getQueryFilter = loadFields + ? getQueryFilterLoadFields(services.dataViews) + : getQueryFilterNoLoadFields; const queryFilter = () => { if (query != null && language != null && index != null) { return getQueryFilter({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter_load_fields.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter_load_fields.ts new file mode 100644 index 0000000000000..d1c8eab7ac2c2 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter_load_fields.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Language } from '@kbn/securitysolution-io-ts-alerting-types'; +import type { Filter, EsQueryConfig, DataViewFieldBase } from '@kbn/es-query'; +import { DataView } from '@kbn/data-views-plugin/server'; +import { queryToFields } from '@kbn/data-plugin/common'; +import type { DataViewsContract } from '@kbn/data-views-plugin/common'; +import type { FieldFormatsStartCommon } from '@kbn/field-formats-plugin/common'; +import { buildEsQuery } from '@kbn/es-query'; +import type { ESBoolQuery } from '../../../../../common/typed_json'; +import { getAllFilters } from './get_query_filter'; +import type { + IndexPatternArray, + RuleQuery, +} from '../../../../../common/api/detection_engine/model/rule_schema'; + +export const getQueryFilterLoadFields = + (dataViewsService: DataViewsContract) => + async ({ + query, + language, + filters, + index, + exceptionFilter, + }: { + query: RuleQuery; + language: Language; + filters: unknown; + index: IndexPatternArray; + exceptionFilter: Filter | undefined; + fields?: DataViewFieldBase[]; + }): Promise => { + const config: EsQueryConfig = { + allowLeadingWildcards: true, + queryStringOptions: { analyze_wildcard: true }, + ignoreFilterIfFieldNotInIndex: false, + dateFormatTZ: 'Zulu', + }; + + const initialQuery = { query, language }; + const allFilters = getAllFilters(filters as Filter[], exceptionFilter); + + const title = (index ?? []).join(); + + const dataViewLazy = await dataViewsService.createDataViewLazy({ title }); + + const flds = await queryToFields({ + dataView: dataViewLazy, + request: { query: [initialQuery], filters: allFilters }, + }); + + const dataViewLimitedFields = new DataView({ + spec: { title }, + fieldFormats: {} as unknown as FieldFormatsStartCommon, + shortDotsEnable: false, + metaFields: [], + }); + + dataViewLimitedFields.fields.replaceAll(Object.values(flds).map((fld) => fld.toSpec())); + + return buildEsQuery(dataViewLimitedFields, initialQuery, allFilters, config); + }; From 072cad1ab80827b06a20a297b6788776c3ce34e0 Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Tue, 18 Jun 2024 17:39:06 -0500 Subject: [PATCH 085/127] [Security Solution][Notes] - add feature flag, new expandable flyout tab and manage entry (#186299) --- packages/deeplinks/security/deep_links.ts | 1 + .../security_solution/common/constants.ts | 16 +------- .../common/experimental_features.ts | 5 +++ .../public/app/translations.ts | 17 ++------- .../left/components/notes_details.tsx | 18 +++++++++ .../flyout/document_details/left/index.tsx | 18 ++++++--- .../flyout/document_details/left/tabs.tsx | 14 +++++++ .../document_details/left/tabs/notes_tab.tsx | 25 ++++++++++++ .../document_details/left/tabs/test_ids.ts | 1 + .../flyout/document_details/left/test_ids.ts | 1 + .../public/management/links.ts | 20 ++++++++++ .../notes/pages/note_management_page.tsx | 18 +++++++++ .../public/timelines/routes.tsx | 38 ++++++++++++++++--- .../translations/translations/fr-FR.json | 3 -- .../translations/translations/ja-JP.json | 3 -- .../translations/translations/zh-CN.json | 3 -- 16 files changed, 153 insertions(+), 48 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/notes_tab.tsx create mode 100644 x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx diff --git a/packages/deeplinks/security/deep_links.ts b/packages/deeplinks/security/deep_links.ts index ea1d818cf8010..c127a8bfafdf2 100644 --- a/packages/deeplinks/security/deep_links.ts +++ b/packages/deeplinks/security/deep_links.ts @@ -86,4 +86,5 @@ export enum SecurityPageName { entityAnalyticsManagement = 'entity_analytics-management', entityAnalyticsAssetClassification = 'entity_analytics-asset-classification', coverageOverview = 'coverage-overview', + notesManagement = 'notes-management', } diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 1822e6be5cb81..70fb550e798e1 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -121,20 +121,7 @@ export const ENTITY_ANALYTICS_PATH = '/entity_analytics' as const; export const ENTITY_ANALYTICS_MANAGEMENT_PATH = `/entity_analytics_management` as const; export const ENTITY_ANALYTICS_ASSET_CRITICALITY_PATH = `/entity_analytics_asset_criticality` as const; -export const APP_OVERVIEW_PATH = `${APP_PATH}${OVERVIEW_PATH}` as const; -export const APP_LANDING_PATH = `${APP_PATH}${LANDING_PATH}` as const; -export const APP_DETECTION_RESPONSE_PATH = `${APP_PATH}${DETECTION_RESPONSE_PATH}` as const; -export const APP_MANAGEMENT_PATH = `${APP_PATH}${MANAGEMENT_PATH}` as const; - export const APP_ALERTS_PATH = `${APP_PATH}${ALERTS_PATH}` as const; -export const APP_RULES_PATH = `${APP_PATH}${RULES_PATH}` as const; -export const APP_EXCEPTIONS_PATH = `${APP_PATH}${EXCEPTIONS_PATH}` as const; - -export const APP_HOSTS_PATH = `${APP_PATH}${HOSTS_PATH}` as const; -export const APP_USERS_PATH = `${APP_PATH}${USERS_PATH}` as const; -export const APP_NETWORK_PATH = `${APP_PATH}${NETWORK_PATH}` as const; -export const APP_KUBERNETES_PATH = `${APP_PATH}${KUBERNETES_PATH}` as const; -export const APP_TIMELINES_PATH = `${APP_PATH}${TIMELINES_PATH}` as const; export const APP_CASES_PATH = `${APP_PATH}${CASES_PATH}` as const; export const APP_ENDPOINTS_PATH = `${APP_PATH}${ENDPOINTS_PATH}` as const; export const APP_POLICIES_PATH = `${APP_PATH}${POLICIES_PATH}` as const; @@ -145,8 +132,7 @@ export const APP_HOST_ISOLATION_EXCEPTIONS_PATH = export const APP_BLOCKLIST_PATH = `${APP_PATH}${BLOCKLIST_PATH}` as const; export const APP_RESPONSE_ACTIONS_HISTORY_PATH = `${APP_PATH}${RESPONSE_ACTIONS_HISTORY_PATH}` as const; -export const APP_ENTITY_ANALYTICS_PATH = `${APP_PATH}${ENTITY_ANALYTICS_PATH}` as const; -export const APP_DATA_QUALITY_PATH = `${APP_PATH}${DATA_QUALITY_PATH}` as const; +export const NOTES_MANAGEMENT_PATH = `/notes_management` as const; // cloud logs to exclude from default index pattern export const EXCLUDE_ELASTIC_CLOUD_INDICES = ['-*elastic-cloud-logs-*']; diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 1a42a4dcce371..761ec8d26035f 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -114,6 +114,11 @@ export const allowedExperimentalValues = Object.freeze({ */ expandableFlyoutDisabled: false, + /** + * Enables new notes + */ + notesEnabled: false, + /** * Enables the Assistant Model Evaluation advanced setting and API endpoint, introduced in `8.11.0`. */ diff --git a/x-pack/plugins/security_solution/public/app/translations.ts b/x-pack/plugins/security_solution/public/app/translations.ts index 0449881d6a636..dcadd74245f24 100644 --- a/x-pack/plugins/security_solution/public/app/translations.ts +++ b/x-pack/plugins/security_solution/public/app/translations.ts @@ -25,6 +25,10 @@ export const ENTITY_ANALYTICS_RISK_SCORE = i18n.translate( } ); +export const NOTES = i18n.translate('xpack.securitySolution.navigation.notesManagement', { + defaultMessage: 'Notes', +}); + export const ASSET_CRITICALITY = i18n.translate( 'xpack.securitySolution.navigation.assetCriticality', { @@ -143,12 +147,6 @@ export const HOST_ISOLATION_EXCEPTIONS = i18n.translate( defaultMessage: 'Host isolation exceptions', } ); -export const DETECT = i18n.translate('xpack.securitySolution.navigation.detect', { - defaultMessage: 'Detect', -}); -export const FINDINGS = i18n.translate('xpack.securitySolution.navigation.findings', { - defaultMessage: 'Findings', -}); export const EXPLORE = i18n.translate('xpack.securitySolution.navigation.explore', { defaultMessage: 'Explore', }); @@ -177,10 +175,3 @@ export const PROTECTION_UPDATES = i18n.translate( export const CREATE_NEW_RULE = i18n.translate('xpack.securitySolution.navigation.newRuleTitle', { defaultMessage: 'Create new rule', }); - -export const THREAT_INTELLIGENCE = i18n.translate( - 'xpack.securitySolution.navigation.threatIntelligence', - { - defaultMessage: 'Intelligence', - } -); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx new file mode 100644 index 0000000000000..3c23ab55cff0f --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo } from 'react'; + +/** + * List all the notes for a document id and allows to create new notes associated with that document. + * Displayed in the document details expandable flyout left section. + */ +export const NotesDetails = memo(() => { + return <>; +}); + +NotesDetails.displayName = 'NotesDetails'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/index.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/index.tsx index 84e9d2553a422..a93b1e7e7a4fb 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/index.tsx @@ -9,6 +9,7 @@ import type { FC } from 'react'; import React, { memo, useMemo } from 'react'; import type { FlyoutPanelProps, PanelPath } from '@kbn/expandable-flyout'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { DocumentDetailsLeftPanelKey } from '../shared/constants/panel_keys'; import { useKibana } from '../../../common/lib/kibana'; import { PanelHeader } from './header'; @@ -20,11 +21,12 @@ import { EventKind } from '../shared/constants/event_kinds'; import { useLeftPanelContext } from './context'; import { LeftPanelTour } from './components/tour'; -export type LeftPanelPaths = 'visualize' | 'insights' | 'investigation' | 'response'; +export type LeftPanelPaths = 'visualize' | 'insights' | 'investigation' | 'response' | 'notes'; export const LeftPanelVisualizeTab: LeftPanelPaths = 'visualize'; export const LeftPanelInsightsTab: LeftPanelPaths = 'insights'; export const LeftPanelInvestigationTab: LeftPanelPaths = 'investigation'; export const LeftPanelResponseTab: LeftPanelPaths = 'response'; +export const LeftPanelNotesTab: LeftPanelPaths = 'notes'; export interface LeftPanelProps extends FlyoutPanelProps { key: typeof DocumentDetailsLeftPanelKey; @@ -41,14 +43,18 @@ export const LeftPanel: FC> = memo(({ path }) => { const { openLeftPanel } = useExpandableFlyoutApi(); const { eventId, indexName, scopeId, getFieldsData } = useLeftPanelContext(); const eventKind = getField(getFieldsData('event.kind')); + const notesEnabled = useIsExperimentalFeatureEnabled('notesEnabled'); - const tabsDisplayed = useMemo( - () => + const tabsDisplayed = useMemo(() => { + const tabList = eventKind === EventKind.signal ? [tabs.insightsTab, tabs.investigationTab, tabs.responseTab] - : [tabs.insightsTab], - [eventKind] - ); + : [tabs.insightsTab]; + if (notesEnabled) { + tabList.push(tabs.notesTab); + } + return tabList; + }, [eventKind, notesEnabled]); const selectedTabId = useMemo(() => { const defaultTab = tabsDisplayed[0].id; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs.tsx index 4851f4a455959..6a066ffb34648 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs.tsx @@ -8,6 +8,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import { NotesTab } from './tabs/notes_tab'; import { VisualizeTab } from './tabs/visualize_tab'; import { InvestigationTab } from './tabs/investigation_tab'; import { InsightsTab } from './tabs/insights_tab'; @@ -15,6 +16,7 @@ import type { LeftPanelPaths } from '.'; import { INSIGHTS_TAB_TEST_ID, INVESTIGATION_TAB_TEST_ID, + NOTES_TAB_TEST_ID, RESPONSE_TAB_TEST_ID, VISUALIZE_TAB_TEST_ID, } from './test_ids'; @@ -74,3 +76,15 @@ export const responseTab: LeftPanelTabType = { ), content: , }; + +export const notesTab: LeftPanelTabType = { + id: 'notes', + 'data-test-subj': NOTES_TAB_TEST_ID, + name: ( + + ), + content: , +}; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/notes_tab.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/notes_tab.tsx new file mode 100644 index 0000000000000..5f95fc67478aa --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/notes_tab.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo } from 'react'; +import { EuiPanel } from '@elastic/eui'; +import { NotesDetails } from '../components/notes_details'; +import { NOTES_TAB_CONTENT_TEST_ID } from './test_ids'; + +/** + * Notes view displayed in the document details expandable flyout left section + * // TODO to be implemented + */ +export const NotesTab = memo(() => { + return ( + + + + ); +}); + +NotesTab.displayName = 'NotesTab'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/test_ids.ts index 4630a19d08c98..1e99fb63d18a5 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/tabs/test_ids.ts @@ -29,3 +29,4 @@ export const INSIGHTS_TAB_CORRELATIONS_BUTTON_TEST_ID = `${INSIGHTS_TAB_TEST_ID}CorrelationsButton` as const; export const INVESTIGATION_TAB_CONTENT_TEST_ID = `${PREFIX}InvestigationsTabContent` as const; export const RESPONSE_TAB_CONTENT_TEST_ID = `${PREFIX}ResponseTabContent` as const; +export const NOTES_TAB_CONTENT_TEST_ID = `${PREFIX}NotesTabContent` as const; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts index beb7971b3a861..9f5eeb035786c 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/test_ids.ts @@ -11,3 +11,4 @@ export const VISUALIZE_TAB_TEST_ID = `${PREFIX}VisualizeTab` as const; export const INSIGHTS_TAB_TEST_ID = `${PREFIX}InsightsTab` as const; export const INVESTIGATION_TAB_TEST_ID = `${PREFIX}InvestigationTab` as const; export const RESPONSE_TAB_TEST_ID = `${PREFIX}ResponseTab` as const; +export const NOTES_TAB_TEST_ID = `${PREFIX}NotesTab` as const; diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index 91bf4e958f6fb..21a5fc69ca1d9 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -22,6 +22,7 @@ import { EVENT_FILTERS_PATH, HOST_ISOLATION_EXCEPTIONS_PATH, MANAGE_PATH, + NOTES_MANAGEMENT_PATH, POLICIES_PATH, RESPONSE_ACTIONS_HISTORY_PATH, SecurityPageName, @@ -39,6 +40,7 @@ import { TRUSTED_APPLICATIONS, ENTITY_ANALYTICS_RISK_SCORE, ASSET_CRITICALITY, + NOTES, } from '../app/translations'; import { licenseService } from '../common/hooks/use_license'; import type { LinkItem } from '../common/links/types'; @@ -85,6 +87,12 @@ const categories = [ }), linkIds: [SecurityPageName.cloudDefendPolicies], }, + { + label: i18n.translate('xpack.securitySolution.appLinks.category.investigations', { + defaultMessage: 'Investigations', + }), + linkIds: [SecurityPageName.notesManagement], + }, ]; export const links: LinkItem = { @@ -215,6 +223,18 @@ export const links: LinkItem = { hideTimeline: true, }, cloudDefendLink, + { + id: SecurityPageName.notesManagement, + title: NOTES, + description: i18n.translate('xpack.securitySolution.appLinks.notesManagementDescription', { + defaultMessage: 'Visualize and delete notes.', + }), + landingIcon: IconTool, // TODO get new icon + path: NOTES_MANAGEMENT_PATH, + skipUrlState: true, + hideTimeline: true, + experimentalKey: 'notesEnabled', + }, ], }; diff --git a/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx b/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx new file mode 100644 index 0000000000000..1964fa65fd96f --- /dev/null +++ b/x-pack/plugins/security_solution/public/notes/pages/note_management_page.tsx @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +/** + * Page to allow users to manage notes. The page is accessible via the Investigations section within the Manage page. + * // TODO to be implemented + */ +export const NoteManagementPage = () => { + return <>; +}; + +NoteManagementPage.displayName = 'NoteManagementPage'; diff --git a/x-pack/plugins/security_solution/public/timelines/routes.tsx b/x-pack/plugins/security_solution/public/timelines/routes.tsx index b64c80cd23036..a7d6373007192 100644 --- a/x-pack/plugins/security_solution/public/timelines/routes.tsx +++ b/x-pack/plugins/security_solution/public/timelines/routes.tsx @@ -5,14 +5,38 @@ * 2.0. */ -import React from 'react'; +import React, { memo } from 'react'; import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; -import { Timelines } from './pages'; -import { TIMELINES_PATH } from '../../common/constants'; -import type { SecuritySubPluginRoutes } from '../app/types'; -import { SecurityPageName } from '../app/types'; +import { Switch } from 'react-router-dom'; +import { Route } from '@kbn/shared-ux-router'; +import { SpyRoute } from '../common/utils/route/spy_routes'; +import { NotFoundPage } from '../app/404'; +import { NoteManagementPage } from '../notes/pages/note_management_page'; import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper'; +import { SecurityPageName } from '../app/types'; +import type { SecuritySubPluginRoutes } from '../app/types'; +import { NOTES_MANAGEMENT_PATH, TIMELINES_PATH } from '../../common/constants'; +import { Timelines } from './pages'; + +const NoteManagementTelemetry = () => ( + + + + + + +); + +const NoteManagementContainer = memo(() => { + return ( + + + + + ); +}); +NoteManagementContainer.displayName = 'NoteManagementContainer'; const TimelinesRoutes = () => ( @@ -27,4 +51,8 @@ export const routes: SecuritySubPluginRoutes = [ path: TIMELINES_PATH, component: TimelinesRoutes, }, + { + path: NOTES_MANAGEMENT_PATH, + component: NoteManagementContainer, + }, ]; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index cf8a0222a0378..d8143a8c98bf3 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -36624,7 +36624,6 @@ "xpack.securitySolution.navigation.case": "Cas", "xpack.securitySolution.navigation.coverageOverviewDashboard": "Couverture MITRE ATT&CK®", "xpack.securitySolution.navigation.dashboards": "Tableaux de bord", - "xpack.securitySolution.navigation.detect": "Détecter", "xpack.securitySolution.navigation.detectionResponse": "Détection et réponse", "xpack.securitySolution.navigation.detectionRules": "Règles de détection (SIEM)", "xpack.securitySolution.navigation.ecsDataQualityDashboard": "Qualité des données", @@ -36632,7 +36631,6 @@ "xpack.securitySolution.navigation.entityRiskScore": "Score de risque des entités", "xpack.securitySolution.navigation.exceptions": "Listes d'exceptions partagées", "xpack.securitySolution.navigation.explore": "Explorer", - "xpack.securitySolution.navigation.findings": "Résultats", "xpack.securitySolution.navigation.gettingStarted": "Démarrer", "xpack.securitySolution.navigation.hosts": "Hôtes", "xpack.securitySolution.navigation.kubernetes": "Kubernetes", @@ -36644,7 +36642,6 @@ "xpack.securitySolution.navigation.protectionUpdates": "Mises à jour de la protection", "xpack.securitySolution.navigation.responseActionsHistory": "Historique des actions de réponse", "xpack.securitySolution.navigation.rules": "Règles", - "xpack.securitySolution.navigation.threatIntelligence": "Intelligence", "xpack.securitySolution.navigation.timelines": "Chronologies", "xpack.securitySolution.navigation.users": "Utilisateurs", "xpack.securitySolution.network.ipDetails.ipOverview.asDestinationDropDownOptionLabel": "Comme destination", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c50d9b9b36b2f..f5b22bce86c92 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -36599,7 +36599,6 @@ "xpack.securitySolution.navigation.case": "ケース", "xpack.securitySolution.navigation.coverageOverviewDashboard": "MITRE ATT&CK®の範囲", "xpack.securitySolution.navigation.dashboards": "ダッシュボード", - "xpack.securitySolution.navigation.detect": "検知", "xpack.securitySolution.navigation.detectionResponse": "検出と対応", "xpack.securitySolution.navigation.detectionRules": "検出ルール(SIEM)", "xpack.securitySolution.navigation.ecsDataQualityDashboard": "データ品質", @@ -36607,7 +36606,6 @@ "xpack.securitySolution.navigation.entityRiskScore": "エンティティリスクスコア", "xpack.securitySolution.navigation.exceptions": "共有例外リスト", "xpack.securitySolution.navigation.explore": "探索", - "xpack.securitySolution.navigation.findings": "調査結果", "xpack.securitySolution.navigation.gettingStarted": "使ってみる", "xpack.securitySolution.navigation.hosts": "ホスト", "xpack.securitySolution.navigation.kubernetes": "Kubernetes", @@ -36619,7 +36617,6 @@ "xpack.securitySolution.navigation.protectionUpdates": "保護更新", "xpack.securitySolution.navigation.responseActionsHistory": "対応アクション履歴", "xpack.securitySolution.navigation.rules": "ルール", - "xpack.securitySolution.navigation.threatIntelligence": "インテリジェンス", "xpack.securitySolution.navigation.timelines": "タイムライン", "xpack.securitySolution.navigation.users": "ユーザー", "xpack.securitySolution.network.ipDetails.ipOverview.asDestinationDropDownOptionLabel": "送信先として", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index cbfe1c3c90544..d94eb2aed9eb7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -36642,7 +36642,6 @@ "xpack.securitySolution.navigation.case": "案例", "xpack.securitySolution.navigation.coverageOverviewDashboard": "MITRE ATT&CK® 支持", "xpack.securitySolution.navigation.dashboards": "仪表板", - "xpack.securitySolution.navigation.detect": "检测", "xpack.securitySolution.navigation.detectionResponse": "检测和响应", "xpack.securitySolution.navigation.detectionRules": "检测规则 (SIEM)", "xpack.securitySolution.navigation.ecsDataQualityDashboard": "数据质量", @@ -36650,7 +36649,6 @@ "xpack.securitySolution.navigation.entityRiskScore": "实体风险分数", "xpack.securitySolution.navigation.exceptions": "共享例外列表", "xpack.securitySolution.navigation.explore": "浏览", - "xpack.securitySolution.navigation.findings": "结果", "xpack.securitySolution.navigation.gettingStarted": "开始使用", "xpack.securitySolution.navigation.hosts": "主机", "xpack.securitySolution.navigation.kubernetes": "Kubernetes", @@ -36662,7 +36660,6 @@ "xpack.securitySolution.navigation.protectionUpdates": "防护更新", "xpack.securitySolution.navigation.responseActionsHistory": "响应操作历史记录", "xpack.securitySolution.navigation.rules": "规则", - "xpack.securitySolution.navigation.threatIntelligence": "情报", "xpack.securitySolution.navigation.timelines": "时间线", "xpack.securitySolution.navigation.users": "用户", "xpack.securitySolution.network.ipDetails.ipOverview.asDestinationDropDownOptionLabel": "作为目标", From fc6838c6ceaf2dbf029b7871cf7d51d91e86dfcc Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:38:55 +0100 Subject: [PATCH 086/127] skip flaky suite (#186387) --- .../pages/cis_integrations/kspm/cis_integration_eks.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts index 3d115fd33f8bf..22b661dbbdc68 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts @@ -108,7 +108,8 @@ export default function (providerContext: FtrProviderContext) { }); }); - describe('KSPM EKS Shared Credentials', () => { + // FLAKY: https://github.com/elastic/kibana/issues/186387 + describe.skip('KSPM EKS Shared Credentials', () => { it('KSPM EKS Shared Credentials Workflow', async () => { const sharedCredentialFile = 'sharedCredentialFileTest'; const sharedCredentialProfileName = 'sharedCredentialProfileNameTest'; From fe07ada72a1b320bf93b8e260cefa4242b2c04d8 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:40:20 +0100 Subject: [PATCH 087/127] skip flaky suite (#186302) --- .../pages/cis_integrations/cnvm/cis_integration_cnvm.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cnvm/cis_integration_cnvm.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cnvm/cis_integration_cnvm.ts index 1e5ff7868f902..1b57e9a65d41e 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cnvm/cis_integration_cnvm.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cnvm/cis_integration_cnvm.ts @@ -23,7 +23,8 @@ export default function (providerContext: FtrProviderContext) { await cisIntegration.navigateToAddIntegrationCspmPage(); }); - describe('CNVM AWS', () => { + // FLAKY: https://github.com/elastic/kibana/issues/186302 + describe.skip('CNVM AWS', () => { it('Hyperlink on PostInstallation Modal should have the correct URL', async () => { await cisIntegration.navigateToAddIntegrationCnvmPage(); await cisIntegration.clickSaveButton(); From d2809ada066e4868406f9b14bc326b3ea82ded87 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:45:18 +0100 Subject: [PATCH 088/127] skip flaky suite (#186389) --- .../pages/cis_integrations/kspm/cis_integration_eks.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts index 22b661dbbdc68..cd63bc117224d 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/kspm/cis_integration_eks.ts @@ -75,7 +75,8 @@ export default function (providerContext: FtrProviderContext) { }); }); - describe('KSPM EKS Temporary Keys', () => { + // FLAKY: https://github.com/elastic/kibana/issues/186389 + describe.skip('KSPM EKS Temporary Keys', () => { it('KSPM EKS Temporary Keys Workflow', async () => { const accessKeyId = 'accessKeyIdTest'; const accessKeySecretKey = 'accessKeySecretKeyTest'; From 404e8c9374e9b9f5a9bae490d43db2eed65f1c1d Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:47:42 +0100 Subject: [PATCH 089/127] skip flaky suite (#185216) --- .../test_suites/common/index_management/inference_endpoints.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts b/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts index cacf294b4c81a..87b760d84540c 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts @@ -18,7 +18,8 @@ export default function ({ getService }: FtrProviderContext) { const taskType = 'sparse_embedding'; const service = 'elser'; - describe('Inference endpoints', function () { + // FLAKY: https://github.com/elastic/kibana/issues/185216 + describe.skip('Inference endpoints', function () { // test adds new trained model '.elser_model_2_linux-x86_64', but does not clean it. Follow up tests are affected this.tags(['failsOnMKI']); before(async () => { From f74ada83958d1c5682b3fdf0b319b64520007f2b Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:49:18 +0100 Subject: [PATCH 090/127] skip flaky suite (#186416) --- test/functional/apps/discover/esql/_esql_columns.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/discover/esql/_esql_columns.ts b/test/functional/apps/discover/esql/_esql_columns.ts index ba7f8447529ab..d48ec83f6ba91 100644 --- a/test/functional/apps/discover/esql/_esql_columns.ts +++ b/test/functional/apps/discover/esql/_esql_columns.ts @@ -36,7 +36,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { defaultIndex: 'logstash-*', }; - describe('discover esql columns', async function () { + // FLAKY: https://github.com/elastic/kibana/issues/186416 + describe.skip('discover esql columns', async function () { before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); From 2d6484d0f4b43d99473221c0c627a76ac3a078e8 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:51:11 +0100 Subject: [PATCH 091/127] skip flaky suite (#157642) --- .../apps/cases/group2/attachment_framework.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts index 876e4d2123019..8c4dd47532255 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts @@ -263,7 +263,8 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); }); - describe('Modal', () => { + // FLAKY: https://github.com/elastic/kibana/issues/157642 + describe.skip('Modal', () => { const createdCases = new Map(); const openModal = async () => { From 2194f85314b7c46d6614bbd177dddb37e8ac2e9c Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 01:52:35 +0100 Subject: [PATCH 092/127] skip flaky suite (#184681) --- .../apis/integrations/inputs_with_standalone_docker_agent.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts b/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts index ca1d8c0c3f312..64a9077b916d9 100644 --- a/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts +++ b/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts @@ -25,7 +25,8 @@ export default function (providerContext: FtrProviderContext) { const config = getService('config'); const log = getService('log'); - describe('inputs_with_standalone_docker_agent', () => { + // FLAKY: https://github.com/elastic/kibana/issues/184681 + describe.skip('inputs_with_standalone_docker_agent', () => { skipIfNoDockerRegistry(providerContext); let apiKey: string; let agent: AgentProcess; From 1c7b5952b31cea4ed68ba2df5ad34ba043bd8852 Mon Sep 17 00:00:00 2001 From: Ryan Keairns Date: Tue, 18 Jun 2024 18:27:39 -0700 Subject: [PATCH 093/127] [ES|QL] Theme updates for text based languages editor (#186345) ## Summary This is a design pass at the editor. Functionality and layout have not been changed. ### What has changed? - Color settings in the `esql_theme.ts` - Added additional rule groups for color treatment (e.g. more operators and values) - Replaced hardcoded style values with EUI variables - As a result, one set of theme colors now works across light and dark mode - Made a few small Monaco configuration (i.e. options) changes that affect the UI/visual output (e.g. active line styles, line height, font... the font size is the same, but I believe these other changes will make it feel larger/more readable) - Re-ordered the options set to more easily find what is/is not enabled - Shortened the height of the top bar; tightened up the padding; more closely matches the footer design ### How does it look? *Light mode* ![CleanShot 2024-06-17 at 16 13 46@2x](https://github.com/elastic/kibana/assets/446285/5e78c2ac-5be8-4138-b1bf-616373c98bf1) *Dark mode* ![CleanShot 2024-06-17 at 16 15 49@2x](https://github.com/elastic/kibana/assets/446285/f739742e-92d8-46d0-a4d2-26f8f2669044) *Compact* ![CleanShot 2024-06-17 at 16 15 26@2x](https://github.com/elastic/kibana/assets/446285/a0f2b129-5973-4742-b428-16ef4f8b1eca) ### What about the other things we saw in the Slack screenshots... I have some other ideas cookin', but I would like to iterate on those concepts in Figma and get additional feedback. These entail the edge-to-edge design, less borders, consolidated header and footer, smaller CTA buttons, full-height field list, etc. Something like this...

Additional design considerations not in this PR ![CleanShot 2024-06-14 at 22 38 34@2x](https://github.com/elastic/kibana/assets/446285/dd5e0f12-1c9a-4ade-ad80-22376f841a41)
### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../kbn-monaco/src/esql/lib/esql_theme.ts | 70 ++++++++++++++----- .../src/editor_footer.tsx | 6 -- .../kbn-text-based-editor/src/overwrite.scss | 66 ++++++++++------- .../src/query_history.tsx | 2 + .../src/text_based_languages_editor.styles.ts | 6 +- .../src/text_based_languages_editor.tsx | 56 ++++++++------- .../query_string_input/query_bar_top_row.tsx | 4 +- 7 files changed, 130 insertions(+), 80 deletions(-) diff --git a/packages/kbn-monaco/src/esql/lib/esql_theme.ts b/packages/kbn-monaco/src/esql/lib/esql_theme.ts index f9ed8c6849acc..c88a8fc02b26d 100644 --- a/packages/kbn-monaco/src/esql/lib/esql_theme.ts +++ b/packages/kbn-monaco/src/esql/lib/esql_theme.ts @@ -12,15 +12,6 @@ import { ESQL_TOKEN_POSTFIX } from './constants'; import { monaco } from '../../monaco_imports'; const buildRuleGroup = themeRuleGroupBuilderFactory(ESQL_TOKEN_POSTFIX); -const COMMANDS_COLORS = { - dark: '#a68ac5', - light: '#765b96', -}; - -const FUNCTIONS_COLORS = { - dark: '#d97797', - light: '#a34a68', -}; export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ base: darkMode ? 'vs-dark' : 'vs', @@ -55,10 +46,16 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ euiThemeVars.euiTextColor ), + // source commands + ...buildRuleGroup( + ['from', 'row', 'show', 'meta'], + euiThemeVars.euiColorPrimaryText, + true // isBold + ), + // commands ...buildRuleGroup( [ - 'from', 'metrics', 'metadata', 'mv_expand', @@ -80,9 +77,6 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'in', 'as', 'expr_ws', - 'row', - 'show', - 'meta', 'limit', 'nulls_ordering_direction', 'nulls_ordering', @@ -90,17 +84,37 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'enrich', 'on', 'with', + 'asc', + 'desc', ], - darkMode ? COMMANDS_COLORS.dark : COMMANDS_COLORS.light + euiThemeVars.euiColorAccentText, + true // isBold ), // functions - ...buildRuleGroup(['functions'], darkMode ? FUNCTIONS_COLORS.dark : FUNCTIONS_COLORS.light), + ...buildRuleGroup(['functions'], euiThemeVars.euiColorPrimaryText), // operators ...buildRuleGroup( - ['or', 'and', 'rp', 'lp', 'plus', 'minus', 'asterisk', 'slash'], - euiThemeVars.euiTextSubduedColor + [ + 'or', + 'and', + 'rp', // ')' + 'lp', // '(' + 'eq', // '==' + 'cieq', // '=~' + 'neq', // '!=' + 'lt', // '<' + 'lte', // '<=' + 'gt', // '>' + 'gte', // '>=' + 'plus', // '+' + 'minus', // '-' + 'asterisk', // '*' + 'slash', // '/' + 'percent', // '%' + ], + euiThemeVars.euiColorPrimaryText ), // comments @@ -113,8 +127,26 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'src_line_comment', 'src_multiline_comment', ], - darkMode ? euiThemeVars.euiColorDarkestShade : euiThemeVars.euiColorMediumShade + euiThemeVars.euiColorDisabledText + ), + + // values + ...buildRuleGroup( + ['quoted_string', 'integer_literal', 'decimal_literal'], + euiThemeVars.euiColorSuccessText ), ], - colors: {}, + colors: { + 'editor.foreground': euiThemeVars.euiTextColor, + 'editor.background': euiThemeVars.euiColorEmptyShade, + 'editor.lineHighlightBackground': euiThemeVars.euiColorLightestShade, + 'editor.lineHighlightBorder': euiThemeVars.euiColorLightestShade, + 'editor.selectionHighlightBackground': euiThemeVars.euiColorLightestShade, + 'editor.selectionHighlightBorder': euiThemeVars.euiColorLightShade, + 'editorSuggestWidget.background': euiThemeVars.euiColorEmptyShade, + 'editorSuggestWidget.border': euiThemeVars.euiColorEmptyShade, + 'editorSuggestWidget.foreground': euiThemeVars.euiTextColor, + 'editorSuggestWidget.selectedBackground': euiThemeVars.euiColorPrimary, + 'editorSuggestWidget.selectedForeground': euiThemeVars.euiColorEmptyShade, + }, }); diff --git a/packages/kbn-text-based-editor/src/editor_footer.tsx b/packages/kbn-text-based-editor/src/editor_footer.tsx index 697563ebc404c..27a6ffbeabbdb 100644 --- a/packages/kbn-text-based-editor/src/editor_footer.tsx +++ b/packages/kbn-text-based-editor/src/editor_footer.tsx @@ -145,7 +145,6 @@ export const EditorFooter = memo(function EditorFooter({ queryHasChanged, measuredContainerWidth, }: EditorFooterProps) { - const { euiTheme } = useEuiTheme(); const [isErrorPopoverOpen, setIsErrorPopoverOpen] = useState(false); const [isWarningPopoverOpen, setIsWarningPopoverOpen] = useState(false); const onUpdateAndSubmit = useCallback( @@ -162,10 +161,6 @@ export const EditorFooter = memo(function EditorFooter({ [runQuery, updateQuery] ); - const shadowStyle = isInCompactMode - ? `inset 0 0px 0, inset 0 -1px 0 ${euiTheme.border.color}` - : 'none'; - return ( diff --git a/packages/kbn-text-based-editor/src/overwrite.scss b/packages/kbn-text-based-editor/src/overwrite.scss index e24fd604d7268..7c66fe96e36cb 100644 --- a/packages/kbn-text-based-editor/src/overwrite.scss +++ b/packages/kbn-text-based-editor/src/overwrite.scss @@ -1,45 +1,63 @@ -.TextBasedLangEditor .monaco-editor { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; +/* Editor styles for any layout mode */ +/* NOTE: Much of this is overriding Monaco styles so the specificity is intentional */ + +// Radius for both the main container and the margin (container for line numbers) +.TextBasedLangEditor .monaco-editor, .TextBasedLangEditor .monaco-editor .margin, .TextBasedLangEditor .monaco-editor .overflow-guard { + border-top-left-radius: $euiBorderRadius; + border-bottom-left-radius: $euiBorderRadius; } .TextBasedLangEditor .monaco-editor .monaco-hover { display: none !important; } -.TextBasedLangEditor--expanded .monaco-editor .monaco-hover { - display: block !important; +.TextBasedLangEditor .monaco-editor .margin-view-overlays .line-numbers { + color: $euiColorDisabledText; } -.TextBasedLangEditor .monaco-editor .margin { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; +// Currently focused line(s) +.TextBasedLangEditor .monaco-editor .current-line ~ .line-numbers { + color: $euiTextSubduedColor; } -.TextBasedLangEditor--compact .monaco-editor { - border-top-left-radius: 0; - border-bottom-left-radius: 0; +// Suggest (autocomplete) menu +.TextBasedLangEditor .monaco-editor .suggest-widget, .TextBasedLangEditor .monaco-editor .suggest-details-container { + @include euiBottomShadow; + border-radius: $euiBorderRadius; } -.TextBasedLangEditor--compact .monaco-editor .margin { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - background-color: $euiColorLightestShade; - color: $euiColorDisabledText; +.TextBasedLangEditor .monaco-editor .suggest-details-container { + background-color: $euiColorEmptyShade; + line-height: 1.5rem; } -.TextBasedLangEditor .monaco-editor .margin-view-overlays .line-numbers { - color: $euiColorDisabledText; +.TextBasedLangEditor_errorMessage { + @include euiTextBreakWord; } -.TextBasedLangEditor .monaco-editor .current-line ~ .line-numbers { - color: $euiTextSubduedColor; -} +/* For compact mode */ +// All scrollable containers (e.g. main container and suggest menu) .TextBasedLangEditor--compact .monaco-editor .monaco-scrollable-element { - margin-left: 4px; + margin-left: $euiSizeS; } -.TextBasedLangEditor_errorMessage { - @include euiTextBreakWord; +// Suggest menu in compact mode +.TextBasedLangEditor--compact .monaco-editor .monaco-list .monaco-scrollable-element { + margin-left: 0; + + .monaco-list-row.focused { + border-radius: $euiBorderRadius; + } } + +/* For expanded mode */ + +.TextBasedLangEditor--expanded .monaco-editor .monaco-hover { + display: block !important; +} + +.TextBasedLangEditor--expanded .monaco-editor, .TextBasedLangEditor--expanded .monaco-editor .margin, .TextBasedLangEditor--expanded .monaco-editor .overflow-guard { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} \ No newline at end of file diff --git a/packages/kbn-text-based-editor/src/query_history.tsx b/packages/kbn-text-based-editor/src/query_history.tsx index d7272e8d59e12..9f0f82deb3db7 100644 --- a/packages/kbn-text-based-editor/src/query_history.tsx +++ b/packages/kbn-text-based-editor/src/query_history.tsx @@ -364,6 +364,8 @@ export function QueryHistory({ .euiTable th[data-test-subj='tableHeaderCell_duration_3'] span { justify-content: flex-end; } + border-bottom-left-radius: ${euiTheme.border.radius.medium}; + border-top-left-radius: ${euiTheme.border.radius.medium}; max-height: ${isInCompactMode ? CONTAINER_MAX_HEIGHT_COMPACT : CONTAINER_MAX_HEIGHT_EXPANDED}px; overflow-y: auto; ${scrollBarStyles} diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts b/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts index 39a02a35516ab..130d0ca69fc4a 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts @@ -102,7 +102,7 @@ export const textBasedLanguageEditorStyles = ( }, historyContainer: { border: euiTheme.border.thin, - borderTop: `2px solid ${euiTheme.colors.lightShade}`, + borderTop: 'none', borderLeft: editorIsInline ? 'none' : euiTheme.border.thin, borderRight: editorIsInline ? 'none' : euiTheme.border.thin, backgroundColor: euiTheme.colors.lightestShade, @@ -119,8 +119,8 @@ export const textBasedLanguageEditorStyles = ( borderTopLeftRadius: editorIsInline ? 0 : euiTheme.border.radius.medium, borderTopRightRadius: editorIsInline ? 0 : euiTheme.border.radius.medium, backgroundColor: euiTheme.colors.lightestShade, - paddingLeft: euiTheme.size.xs, - paddingRight: euiTheme.size.xs, + paddingLeft: euiTheme.size.s, + paddingRight: euiTheme.size.s, paddingTop: showHeader ? euiTheme.size.s : euiTheme.size.xs, paddingBottom: showHeader ? euiTheme.size.s : euiTheme.size.xs, width: '100%', diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index b3729118f6e99..b33d8125bfd25 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -667,41 +667,43 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ }, [language, documentationSections]); const codeEditorOptions: CodeEditorProps['options'] = { - automaticLayout: true, accessibilitySupport: 'off', + autoIndent: 'none', + automaticLayout: true, + fixedOverflowWidgets: true, folding: false, fontSize: 14, - padding: { - top: 8, - bottom: 8, - }, - scrollBeyondLastLine: false, - quickSuggestions: true, - minimap: { enabled: false }, - wordWrap: 'on', - lineNumbers: showLineNumbers ? 'on' : 'off', - theme: language === 'esql' ? ESQL_THEME_ID : isDark ? 'vs-dark' : 'vs', - lineDecorationsWidth: 12, - autoIndent: 'none', - wrappingIndent: 'none', - lineNumbersMinChars: 3, - overviewRulerLanes: 0, hideCursorInOverviewRuler: true, - scrollbar: { - horizontal: 'hidden', - vertical: 'auto', - }, - overviewRulerBorder: false, // this becomes confusing with multiple markers, so quick fixes // will be proposed only within the tooltip lightbulb: { enabled: false, }, - fixedOverflowWidgets: true, + lineDecorationsWidth: 12, + lineNumbers: showLineNumbers ? 'on' : 'off', + lineNumbersMinChars: 3, + minimap: { enabled: false }, + overviewRulerLanes: 0, + overviewRulerBorder: false, + padding: { + top: 8, + bottom: 8, + }, + quickSuggestions: true, readOnly: isLoading || isDisabled || Boolean(!isCompactFocused && codeOneLiner && codeOneLiner.includes('...')), + renderLineHighlight: !isCodeEditorExpanded ? 'none' : 'line', + renderLineHighlightOnlyWhenFocus: true, + scrollbar: { + horizontal: 'hidden', + vertical: 'auto', + }, + scrollBeyondLastLine: false, + theme: language === 'esql' ? ESQL_THEME_ID : isDark ? 'vs-dark' : 'vs', + wordWrap: 'on', + wrappingIndent: 'none', }; if (isCompactFocused) { @@ -743,7 +745,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ {!Boolean(hideMinimizeButton) && ( - + { expandCodeEditor(false); updateLinesFromModel = false; @@ -1015,6 +1017,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ borderRadius: 0, backgroundColor: isDark ? euiTheme.colors.lightestShade : '#e9edf3', border: '1px solid rgb(17 43 134 / 10%) !important', + transform: 'none !important', }, }} /> @@ -1044,6 +1047,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ backgroundColor: isDark ? euiTheme.colors.lightestShade : '#e9edf3', border: '1px solid rgb(17 43 134 / 10%) !important', borderLeft: 'transparent !important', + transform: 'none !important', }} /> diff --git a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx index 892144d07fb06..941040dfd30f8 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx @@ -566,7 +566,7 @@ export const QueryBarTopRow = React.memo( : strings.getRefreshQueryLabel(); const buttonLabelRun = textBasedRunShortcut; - const iconDirty = Boolean(isQueryLangSelected) ? 'play' : 'kqlFunction'; + const iconDirty = Boolean(isQueryLangSelected) ? 'playFilled' : 'kqlFunction'; const tooltipDirty = Boolean(isQueryLangSelected) ? buttonLabelRun : buttonLabelUpdate; const isDirtyButtonLabel = Boolean(isQueryLangSelected) @@ -588,7 +588,7 @@ export const QueryBarTopRow = React.memo( onClick={onClickSubmitButton} size={shouldShowDatePickerAsBadge() ? 's' : 'm'} color={props.isDirty ? 'success' : 'primary'} - fill={props.isDirty} + fill={false} needsUpdate={props.isDirty} data-test-subj="querySubmitButton" toolTipProps={{ From 1b872fbf9dc90d3c82a569a9faef9e360fc41171 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Tue, 18 Jun 2024 19:48:07 -0600 Subject: [PATCH 094/127] [Security Assistant] Adds client hooks and internal routes for managing Knowledge Base Entries (#184974) ## Summary This PR adds client hooks and basic REST API's for accessing and mutating Knowledge Base Entries. This is in support of @angorayc building out the new Knowledge Base settings interface. Change set includes: - [X] Refactors existing KB client hooks from `x-pack/packages/kbn-elastic-assistant/impl/knowledge_base` to be co-located next to the API methods where we put all our other hooks: `x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base` - [X] Refactors existing KB API calls and associated tests out of `kbn-elastic-assistant/impl/assistant/api/index.tsx` and into `x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.tsx` - [X] Adds new `find_knowledge_base_entries_route.schema.yaml` OAS for the supporting `/internal/elastic_assistant/knowledge_base/entries/_find` route - [X] Refactors `SortOrder` out of existing OAS's into the shared `schemas/common_attributes.schema.yaml` ### Client Hooks & Routes Adds new `useKnowledgeBaseEntries()` hook and corresponding `/knowledge_base/entries/_find` route for returning paginated KB Entries to populate the KB table in settings. E.g. ``` ts const { assistantFeatures: { assistantKnowledgeBaseByDefault: enableKnowledgeBaseByDefault }, http, toasts, } = useAssistantContext(); const { data: kbEntries, isLoading: isLoadingEntries } = useKnowledgeBaseEntries({ http }); ``` ###### Sample Response ``` json { "perPage": 20, "page": 1, "total": 145, "data": [ { "timestamp": "2024-06-05T21:19:56.482Z", "id": "CtBF6o8BSQy1Bdxt2FHz", "createdAt": "2024-06-05T21:19:56.482Z", "createdBy": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", "updatedAt": "2024-06-05T21:19:56.482Z", "updatedBy": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", "users": [ { "id": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", "name": "elastic" } ], "metadata": { "kbResource": "security_labs", "source": "/Users/garrettspong/dev/kibana-main/x-pack/plugins/elastic_assistant/server/knowledge_base/security_labs/2022_elastic_global_threat_report_announcement.mdx", "required": false }, "namespace": "default", "text": "[Source Content Here]", "vector": { "modelId": ".elser_model_2", "tokens": { "2": 0.06595266, ... } } }, ... ] } ``` Response is the full newly created `entry`. Same format for the entry as above in the `_find` API, and the `KnowledgeBaseEntries` cache is invalidated. Adds new `useCreateKnowledgeBaseEntry()` hook and corresponding `/knowledge_base/entries` route for creating new KB Entries ``` ts const entry: KnowledgeBaseEntryCreateProps = { metadata: { kbResource: 'user', required: true, source: 'user', }, text: 'Useful information about the user', }; const { mutate: createEntry, isLoading: isCreatingEntry } = useCreateKnowledgeBaseEntry({ http, }); await createEntry(entry); ``` Adds new `useDeleteKnowledgeBaseEntries()` hook and corresponding `/knowledge_base/entries/_bulk_action` route for deleting existing KB Entries. I left a TODO to plumb through `delete_by_query` so we can add a filter bar to the table. Need to confirm if we can do pagination with similarity search as well. ``` ts const { mutate: deleteEntries, isLoading: isDeletingEntries } = useDeleteKnowledgeBaseEntries({ http, }); await deleteEntries({ ids: ['YOE_CZABSQy1BdxtAGbs'] }) ``` See `KnowledgeBaseEntryBulkCrudActionResponse` for response formats. `KnowledgeBaseEntries` cache is invalidated upon delete. ### Checklist Delete any items that are not applicable to this PR. - [ ] ~Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~ - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials * Feature currently behind feature flag. Documentation to be added before flag is removed. Tracked in https://github.com/elastic/security-docs/issues/5337 - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] API tests will need to be rounded out as we finalize functionality behind the feature flag --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../kbn-elastic-assistant-common/constants.ts | 5 +- .../impl/capabilities/index.ts | 5 + .../find_anonymization_fields_route.gen.ts | 6 +- ...ind_anonymization_fields_route.schema.yaml | 8 +- .../impl/schemas/common_attributes.gen.ts | 5 + .../schemas/common_attributes.schema.yaml | 6 + .../find_conversations_route.gen.ts | 6 +- .../find_conversations_route.schema.yaml | 10 +- .../impl/schemas/index.ts | 1 + .../common_attributes.schema.yaml | 1 - .../find_knowledge_base_entries_route.gen.ts | 69 +++++ ...d_knowledge_base_entries_route.schema.yaml | 102 ++++++++ .../schemas/prompts/find_prompts_route.gen.ts | 6 +- .../prompts/find_prompts_route.schema.yaml | 8 +- .../impl/assistant/api/index.test.tsx | 83 +------ .../impl/assistant/api/index.tsx | 110 +------- .../assistant/api/knowledge_base/api.test.tsx | 97 ++++++++ .../impl/assistant/api/knowledge_base/api.tsx | 114 +++++++++ .../use_create_knowledge_base_entry.tsx | 83 +++++++ .../use_delete_knowledge_base_entries.tsx | 90 +++++++ .../entries/use_knowledge_base_entries.ts | 80 ++++++ .../use_delete_knowledge_base.test.tsx | 6 +- .../use_delete_knowledge_base.tsx | 2 +- .../use_knowledge_base_status.test.tsx | 6 +- .../use_knowledge_base_status.tsx | 2 +- .../use_setup_knowledge_base.test.tsx | 6 +- .../use_setup_knowledge_base.tsx | 2 +- .../install_knowledge_base_button.tsx | 4 +- .../knowledge_base_settings.test.tsx | 8 +- .../knowledge_base_settings.tsx | 6 +- .../elastic_assistant/common/constants.ts | 3 + .../knowledge_base/index.ts | 8 +- .../langchain/content_loaders/esql_loader.ts | 8 +- .../elasticsearch_store.test.ts | 7 +- .../elasticsearch_store.ts | 5 +- .../server/routes/helpers.ts | 72 +++++- .../entries/bulk_actions_route.ts | 235 ++++++++++++++++++ .../knowledge_base/entries/create_route.ts | 55 ++-- .../knowledge_base/entries/find_route.ts | 103 ++++++++ .../server/routes/register_routes.ts | 10 +- 40 files changed, 1158 insertions(+), 285 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.schema.yaml create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_create_knowledge_base_entry.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_delete_knowledge_base_entries.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_knowledge_base_entries.ts rename x-pack/packages/kbn-elastic-assistant/impl/{ => assistant/api}/knowledge_base/use_delete_knowledge_base.test.tsx (94%) rename x-pack/packages/kbn-elastic-assistant/impl/{ => assistant/api}/knowledge_base/use_delete_knowledge_base.tsx (97%) rename x-pack/packages/kbn-elastic-assistant/impl/{ => assistant/api}/knowledge_base/use_knowledge_base_status.test.tsx (96%) rename x-pack/packages/kbn-elastic-assistant/impl/{ => assistant/api}/knowledge_base/use_knowledge_base_status.tsx (97%) rename x-pack/packages/kbn-elastic-assistant/impl/{ => assistant/api}/knowledge_base/use_setup_knowledge_base.test.tsx (94%) rename x-pack/packages/kbn-elastic-assistant/impl/{ => assistant/api}/knowledge_base/use_setup_knowledge_base.tsx (97%) create mode 100644 x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/bulk_actions_route.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/find_route.ts diff --git a/x-pack/packages/kbn-elastic-assistant-common/constants.ts b/x-pack/packages/kbn-elastic-assistant-common/constants.ts index f30cb053d4ce1..74da6ab2476e2 100755 --- a/x-pack/packages/kbn-elastic-assistant-common/constants.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/constants.ts @@ -27,5 +27,6 @@ export const ELASTIC_AI_ASSISTANT_ANONYMIZATION_FIELDS_URL_FIND = `${ELASTIC_AI_ // TODO: Update existing 'status' endpoint to take resource as query param as to not conflict with 'entries' export const ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL = `${ELASTIC_AI_ASSISTANT_INTERNAL_URL}/knowledge_base/{resource?}`; -export const ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL = `${ELASTIC_AI_ASSISTANT_URL}/knowledge_base/entries`; -export const ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION = `${ELASTIC_AI_ASSISTANT_URL}/knowledge_base/_bulk_action`; +export const ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL = `${ELASTIC_AI_ASSISTANT_INTERNAL_URL}/knowledge_base/entries`; +export const ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND = `${ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL}/_find`; +export const ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION = `${ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL}/_bulk_action`; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/index.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/index.ts index 9c734cc4b3c13..c1c101fd74cd8 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/index.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/index.ts @@ -10,6 +10,11 @@ */ export type AssistantFeatures = { [K in keyof typeof defaultAssistantFeatures]: boolean }; +/** + * Type for keys of the assistant features + */ +export type AssistantFeatureKey = keyof AssistantFeatures; + /** * Default features available to the elastic assistant */ diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.gen.ts index b51ea84170643..486df4547b429 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.gen.ts @@ -17,6 +17,7 @@ import { z } from 'zod'; import { ArrayFromString } from '@kbn/zod-helpers'; +import { SortOrder } from '../common_attributes.gen'; import { AnonymizationFieldResponse } from './bulk_crud_anonymization_fields_route.gen'; export type FindAnonymizationFieldsSortField = z.infer; @@ -30,11 +31,6 @@ export const FindAnonymizationFieldsSortField = z.enum([ export type FindAnonymizationFieldsSortFieldEnum = typeof FindAnonymizationFieldsSortField.enum; export const FindAnonymizationFieldsSortFieldEnum = FindAnonymizationFieldsSortField.enum; -export type SortOrder = z.infer; -export const SortOrder = z.enum(['asc', 'desc']); -export type SortOrderEnum = typeof SortOrder.enum; -export const SortOrderEnum = SortOrder.enum; - export type FindAnonymizationFieldsRequestQuery = z.infer< typeof FindAnonymizationFieldsRequestQuery >; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.schema.yaml index b9b2d1e9e2097..3541c3a1c649b 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/anonymization_fields/find_anonymization_fields_route.schema.yaml @@ -36,7 +36,7 @@ paths: description: Sort order required: false schema: - $ref: '#/components/schemas/SortOrder' + $ref: '../common_attributes.schema.yaml#/components/schemas/SortOrder' - name: 'page' in: query description: Page number @@ -101,9 +101,3 @@ components: - 'allowed' - 'field' - 'updated_at' - - SortOrder: - type: string - enum: - - 'asc' - - 'desc' diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts index d4d4ce5657f62..613d54fa080fb 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts @@ -45,3 +45,8 @@ export const User = z.object({ */ name: z.string().optional(), }); + +export type SortOrder = z.infer; +export const SortOrder = z.enum(['asc', 'desc']); +export type SortOrderEnum = typeof SortOrder.enum; +export const SortOrderEnum = SortOrder.enum; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.schema.yaml index 5c580c52281ad..348868746fb6c 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.schema.yaml @@ -28,3 +28,9 @@ components: type: string description: User name + SortOrder: + type: string + enum: + - 'asc' + - 'desc' + diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts index 556dca3db8214..6f8607640e262 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts @@ -17,6 +17,7 @@ import { z } from 'zod'; import { ArrayFromString } from '@kbn/zod-helpers'; +import { SortOrder } from '../common_attributes.gen'; import { ConversationResponse } from './common_attributes.gen'; export type FindConversationsSortField = z.infer; @@ -29,11 +30,6 @@ export const FindConversationsSortField = z.enum([ export type FindConversationsSortFieldEnum = typeof FindConversationsSortField.enum; export const FindConversationsSortFieldEnum = FindConversationsSortField.enum; -export type SortOrder = z.infer; -export const SortOrder = z.enum(['asc', 'desc']); -export type SortOrderEnum = typeof SortOrder.enum; -export const SortOrderEnum = SortOrder.enum; - export type FindConversationsRequestQuery = z.infer; export const FindConversationsRequestQuery = z.object({ fields: ArrayFromString(z.string()).optional(), diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.schema.yaml index 44cec1a169e51..fcb4c0a013eaa 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.schema.yaml @@ -36,7 +36,7 @@ paths: description: Sort order required: false schema: - $ref: '#/components/schemas/SortOrder' + $ref: '../common_attributes.schema.yaml#/components/schemas/SortOrder' - name: 'page' in: query description: Page number @@ -124,7 +124,7 @@ paths: description: Sort order required: false schema: - $ref: '#/components/schemas/SortOrder' + $ref: '../common_attributes.schema.yaml#/components/schemas/SortOrder' - name: 'page' in: query description: Page number @@ -188,9 +188,3 @@ components: - 'is_default' - 'title' - 'updated_at' - - SortOrder: - type: string - enum: - - 'asc' - - 'desc' diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts index c9c2d2a8be3c0..ae66432af3076 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts @@ -45,3 +45,4 @@ export * from './knowledge_base/crud_kb_route.gen'; export * from './knowledge_base/bulk_crud_knowledge_base_route.gen'; export * from './knowledge_base/common_attributes.gen'; export * from './knowledge_base/crud_knowledge_base_route.gen'; +export * from './knowledge_base/find_knowledge_base_entries_route.gen'; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/common_attributes.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/common_attributes.schema.yaml index 63fcdf16b8fb1..53c69426b69bd 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/common_attributes.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/common_attributes.schema.yaml @@ -121,4 +121,3 @@ components: type: string description: Knowledge Base Entry content - diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts new file mode 100644 index 0000000000000..25db35693c3dc --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Find Knowledge Base Entries API endpoint + * version: 1 + */ + +import { z } from 'zod'; +import { ArrayFromString } from '@kbn/zod-helpers'; + +import { SortOrder } from '../common_attributes.gen'; +import { KnowledgeBaseEntryResponse } from './common_attributes.gen'; + +export type FindKnowledgeBaseEntriesSortField = z.infer; +export const FindKnowledgeBaseEntriesSortField = z.enum([ + 'created_at', + 'is_default', + 'title', + 'updated_at', +]); +export type FindKnowledgeBaseEntriesSortFieldEnum = typeof FindKnowledgeBaseEntriesSortField.enum; +export const FindKnowledgeBaseEntriesSortFieldEnum = FindKnowledgeBaseEntriesSortField.enum; + +export type FindKnowledgeBaseEntriesRequestQuery = z.infer< + typeof FindKnowledgeBaseEntriesRequestQuery +>; +export const FindKnowledgeBaseEntriesRequestQuery = z.object({ + fields: ArrayFromString(z.string()).optional(), + /** + * Search query + */ + filter: z.string().optional(), + /** + * Field to sort by + */ + sort_field: FindKnowledgeBaseEntriesSortField.optional(), + /** + * Sort order + */ + sort_order: SortOrder.optional(), + /** + * Page number + */ + page: z.coerce.number().int().min(1).optional().default(1), + /** + * Knowledge Base Entries per page + */ + per_page: z.coerce.number().int().min(0).optional().default(20), +}); +export type FindKnowledgeBaseEntriesRequestQueryInput = z.input< + typeof FindKnowledgeBaseEntriesRequestQuery +>; + +export type FindKnowledgeBaseEntriesResponse = z.infer; +export const FindKnowledgeBaseEntriesResponse = z.object({ + page: z.number().int(), + perPage: z.number().int(), + total: z.number().int(), + data: z.array(KnowledgeBaseEntryResponse), +}); diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.schema.yaml new file mode 100644 index 0000000000000..d5298ff2ccbdc --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.schema.yaml @@ -0,0 +1,102 @@ +openapi: 3.0.0 +info: + title: Find Knowledge Base Entries API endpoint + version: '1' +paths: + /internal/elastic_assistant/knowledge_base/entries/_find: + get: + operationId: FindKnowledgeBaseEntries + x-codegen-enabled: true + description: Finds Knowledge Base Entries that match the given query. + summary: Finds Knowledge Base Entries that match the given query. + tags: + - Knowledge Base Entries API + parameters: + - name: 'fields' + in: query + required: false + schema: + type: array + items: + type: string + - name: 'filter' + in: query + description: Search query + required: false + schema: + type: string + - name: 'sort_field' + in: query + description: Field to sort by + required: false + schema: + $ref: '#/components/schemas/FindKnowledgeBaseEntriesSortField' + - name: 'sort_order' + in: query + description: Sort order + required: false + schema: + $ref: '../common_attributes.schema.yaml#/components/schemas/SortOrder' + - name: 'page' + in: query + description: Page number + required: false + schema: + type: integer + minimum: 1 + default: 1 + - name: 'per_page' + in: query + description: Knowledge Base Entries per page + required: false + schema: + type: integer + minimum: 0 + default: 20 + + responses: + 200: + description: Successful response + content: + application/json: + schema: + type: object + properties: + page: + type: integer + perPage: + type: integer + total: + type: integer + data: + type: array + items: + $ref: './common_attributes.schema.yaml#/components/schemas/KnowledgeBaseEntryResponse' + required: + - page + - perPage + - total + - data + 400: + description: Generic Error + content: + application/json: + schema: + type: object + properties: + statusCode: + type: number + error: + type: string + message: + type: string + +components: + schemas: + FindKnowledgeBaseEntriesSortField: + type: string + enum: + - 'created_at' + - 'is_default' + - 'title' + - 'updated_at' diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen.ts index bd050f5c8260d..49f4c75029581 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.gen.ts @@ -17,6 +17,7 @@ import { z } from 'zod'; import { ArrayFromString } from '@kbn/zod-helpers'; +import { SortOrder } from '../common_attributes.gen'; import { PromptResponse } from './bulk_crud_prompts_route.gen'; export type FindPromptsSortField = z.infer; @@ -24,11 +25,6 @@ export const FindPromptsSortField = z.enum(['created_at', 'is_default', 'name', export type FindPromptsSortFieldEnum = typeof FindPromptsSortField.enum; export const FindPromptsSortFieldEnum = FindPromptsSortField.enum; -export type SortOrder = z.infer; -export const SortOrder = z.enum(['asc', 'desc']); -export type SortOrderEnum = typeof SortOrder.enum; -export const SortOrderEnum = SortOrder.enum; - export type FindPromptsRequestQuery = z.infer; export const FindPromptsRequestQuery = z.object({ fields: ArrayFromString(z.string()).optional(), diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.schema.yaml index 8e85194811dbc..1902f4e9ae3d9 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/prompts/find_prompts_route.schema.yaml @@ -36,7 +36,7 @@ paths: description: Sort order required: false schema: - $ref: '#/components/schemas/SortOrder' + $ref: '../common_attributes.schema.yaml#/components/schemas/SortOrder' - name: 'page' in: query description: Page number @@ -100,9 +100,3 @@ components: - 'is_default' - 'name' - 'updated_at' - - SortOrder: - type: string - enum: - - 'asc' - - 'desc' diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx index 0182c4061866b..0e89bc7f5738a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.test.tsx @@ -9,13 +9,7 @@ import { HttpSetup } from '@kbn/core-http-browser'; import { ApiConfig } from '@kbn/elastic-assistant-common'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; -import { - deleteKnowledgeBase, - fetchConnectorExecuteAction, - FetchConnectorExecuteAction, - getKnowledgeBaseStatus, - postKnowledgeBase, -} from '.'; +import { fetchConnectorExecuteAction, FetchConnectorExecuteAction } from '.'; import { API_ERROR } from '../translations'; jest.mock('@kbn/core-http-browser'); @@ -303,79 +297,4 @@ describe('API tests', () => { expect(result).toEqual({ response, isStream: false, isError: false }); }); }); - - const knowledgeBaseArgs = { - resource: 'a-resource', - http: mockHttp, - }; - describe('getKnowledgeBaseStatus', () => { - it('calls the knowledge base API when correct resource path', async () => { - await getKnowledgeBaseStatus(knowledgeBaseArgs); - - expect(mockHttp.fetch).toHaveBeenCalledWith( - '/internal/elastic_assistant/knowledge_base/a-resource', - { - method: 'GET', - signal: undefined, - version: '1', - } - ); - }); - it('returns error when error is an error', async () => { - const error = 'simulated error'; - (mockHttp.fetch as jest.Mock).mockImplementation(() => { - throw new Error(error); - }); - - await expect(getKnowledgeBaseStatus(knowledgeBaseArgs)).resolves.toThrowError( - 'simulated error' - ); - }); - }); - - describe('postKnowledgeBase', () => { - it('calls the knowledge base API when correct resource path', async () => { - await postKnowledgeBase(knowledgeBaseArgs); - - expect(mockHttp.fetch).toHaveBeenCalledWith( - '/internal/elastic_assistant/knowledge_base/a-resource', - { - method: 'POST', - signal: undefined, - version: '1', - } - ); - }); - it('returns error when error is an error', async () => { - const error = 'simulated error'; - (mockHttp.fetch as jest.Mock).mockImplementation(() => { - throw new Error(error); - }); - - await expect(postKnowledgeBase(knowledgeBaseArgs)).resolves.toThrowError('simulated error'); - }); - }); - - describe('deleteKnowledgeBase', () => { - it('calls the knowledge base API when correct resource path', async () => { - await deleteKnowledgeBase(knowledgeBaseArgs); - - expect(mockHttp.fetch).toHaveBeenCalledWith( - '/internal/elastic_assistant/knowledge_base/a-resource', - { - method: 'DELETE', - signal: undefined, - version: '1', - } - ); - }); - it('returns error when error is an error', async () => { - const error = 'simulated error'; - (mockHttp.fetch as jest.Mock).mockImplementation(() => { - throw new Error(error); - }); - - await expect(deleteKnowledgeBase(knowledgeBaseArgs)).resolves.toThrowError('simulated error'); - }); - }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx index a554324515ad6..b8c42a787621b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/index.tsx @@ -6,19 +6,7 @@ */ import { HttpSetup } from '@kbn/core/public'; -import { IHttpFetchError } from '@kbn/core-http-browser'; -import { - API_VERSIONS, - ApiConfig, - CreateKnowledgeBaseRequestParams, - CreateKnowledgeBaseResponse, - DeleteKnowledgeBaseRequestParams, - DeleteKnowledgeBaseResponse, - ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL, - ReadKnowledgeBaseRequestParams, - ReadKnowledgeBaseResponse, - Replacements, -} from '@kbn/elastic-assistant-common'; +import { API_VERSIONS, ApiConfig, Replacements } from '@kbn/elastic-assistant-common'; import { API_ERROR } from '../translations'; import { getOptionalRequestParams } from '../helpers'; import { TraceOptions } from '../types'; @@ -185,99 +173,3 @@ export const fetchConnectorExecuteAction = async ({ }; } }; - -/** - * API call for getting the status of the Knowledge Base. Provide - * a resource to include the status of that specific resource. - * - * @param {Object} options - The options object. - * @param {HttpSetup} options.http - HttpSetup - * @param {string} [options.resource] - Resource to get the status of, otherwise status of overall KB - * @param {AbortSignal} [options.signal] - AbortSignal - * - * @returns {Promise} - */ -export const getKnowledgeBaseStatus = async ({ - http, - resource, - signal, -}: ReadKnowledgeBaseRequestParams & { http: HttpSetup; signal?: AbortSignal | undefined }): Promise< - ReadKnowledgeBaseResponse | IHttpFetchError -> => { - try { - const path = ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL.replace('{resource?}', resource || ''); - const response = await http.fetch(path, { - method: 'GET', - signal, - version: API_VERSIONS.internal.v1, - }); - - return response as ReadKnowledgeBaseResponse; - } catch (error) { - return error as IHttpFetchError; - } -}; - -/** - * API call for setting up the Knowledge Base. Provide a resource to set up a specific resource. - * - * @param {Object} options - The options object. - * @param {HttpSetup} options.http - HttpSetup - * @param {string} [options.resource] - Resource to be added to the KB, otherwise sets up the base KB - * @param {AbortSignal} [options.signal] - AbortSignal - * - * @returns {Promise} - */ -export const postKnowledgeBase = async ({ - http, - resource, - signal, -}: CreateKnowledgeBaseRequestParams & { - http: HttpSetup; - signal?: AbortSignal | undefined; -}): Promise => { - try { - const path = ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL.replace('{resource?}', resource || ''); - const response = await http.fetch(path, { - method: 'POST', - signal, - version: API_VERSIONS.internal.v1, - }); - - return response as CreateKnowledgeBaseResponse; - } catch (error) { - return error as IHttpFetchError; - } -}; - -/** - * API call for deleting the Knowledge Base. Provide a resource to delete that specific resource. - * - * @param {Object} options - The options object. - * @param {HttpSetup} options.http - HttpSetup - * @param {string} [options.resource] - Resource to be deleted from the KB, otherwise delete the entire KB - * @param {AbortSignal} [options.signal] - AbortSignal - * - * @returns {Promise} - */ -export const deleteKnowledgeBase = async ({ - http, - resource, - signal, -}: DeleteKnowledgeBaseRequestParams & { - http: HttpSetup; - signal?: AbortSignal | undefined; -}): Promise => { - try { - const path = ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL.replace('{resource?}', resource || ''); - const response = await http.fetch(path, { - method: 'DELETE', - signal, - version: API_VERSIONS.internal.v1, - }); - - return response as DeleteKnowledgeBaseResponse; - } catch (error) { - return error as IHttpFetchError; - } -}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.test.tsx new file mode 100644 index 0000000000000..06ba7d875b64f --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.test.tsx @@ -0,0 +1,97 @@ +/* + * Copyright 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 { HttpSetup } from '@kbn/core-http-browser'; + +import { deleteKnowledgeBase, getKnowledgeBaseStatus, postKnowledgeBase } from './api'; + +jest.mock('@kbn/core-http-browser'); + +const mockHttp = { + fetch: jest.fn(), +} as unknown as HttpSetup; + +describe('API tests', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const knowledgeBaseArgs = { + resource: 'a-resource', + http: mockHttp, + }; + describe('getKnowledgeBaseStatus', () => { + it('calls the knowledge base API when correct resource path', async () => { + await getKnowledgeBaseStatus(knowledgeBaseArgs); + + expect(mockHttp.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/knowledge_base/a-resource', + { + method: 'GET', + signal: undefined, + version: '1', + } + ); + }); + it('returns error when error is an error', async () => { + const error = 'simulated error'; + (mockHttp.fetch as jest.Mock).mockImplementation(() => { + throw new Error(error); + }); + + await expect(getKnowledgeBaseStatus(knowledgeBaseArgs)).resolves.toThrowError( + 'simulated error' + ); + }); + }); + + describe('postKnowledgeBase', () => { + it('calls the knowledge base API when correct resource path', async () => { + await postKnowledgeBase(knowledgeBaseArgs); + + expect(mockHttp.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/knowledge_base/a-resource', + { + method: 'POST', + signal: undefined, + version: '1', + } + ); + }); + it('returns error when error is an error', async () => { + const error = 'simulated error'; + (mockHttp.fetch as jest.Mock).mockImplementation(() => { + throw new Error(error); + }); + + await expect(postKnowledgeBase(knowledgeBaseArgs)).resolves.toThrowError('simulated error'); + }); + }); + + describe('deleteKnowledgeBase', () => { + it('calls the knowledge base API when correct resource path', async () => { + await deleteKnowledgeBase(knowledgeBaseArgs); + + expect(mockHttp.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/knowledge_base/a-resource', + { + method: 'DELETE', + signal: undefined, + version: '1', + } + ); + }); + it('returns error when error is an error', async () => { + const error = 'simulated error'; + (mockHttp.fetch as jest.Mock).mockImplementation(() => { + throw new Error(error); + }); + + await expect(deleteKnowledgeBase(knowledgeBaseArgs)).resolves.toThrowError('simulated error'); + }); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.tsx new file mode 100644 index 0000000000000..65fa1f72064e1 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/api.tsx @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + API_VERSIONS, + CreateKnowledgeBaseRequestParams, + CreateKnowledgeBaseResponse, + DeleteKnowledgeBaseRequestParams, + DeleteKnowledgeBaseResponse, + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL, + ReadKnowledgeBaseRequestParams, + ReadKnowledgeBaseResponse, +} from '@kbn/elastic-assistant-common'; +import { HttpSetup, IHttpFetchError } from '@kbn/core-http-browser'; + +/** + * API call for getting the status of the Knowledge Base. Provide + * a resource to include the status of that specific resource. + * + * @param {Object} options - The options object. + * @param {HttpSetup} options.http - HttpSetup + * @param {string} [options.resource] - Resource to get the status of, otherwise status of overall KB + * @param {AbortSignal} [options.signal] - AbortSignal + * + * @returns {Promise} + */ +export const getKnowledgeBaseStatus = async ({ + http, + resource, + signal, +}: ReadKnowledgeBaseRequestParams & { http: HttpSetup; signal?: AbortSignal | undefined }): Promise< + ReadKnowledgeBaseResponse | IHttpFetchError +> => { + try { + const path = ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL.replace('{resource?}', resource || ''); + const response = await http.fetch(path, { + method: 'GET', + signal, + version: API_VERSIONS.internal.v1, + }); + + return response as ReadKnowledgeBaseResponse; + } catch (error) { + return error as IHttpFetchError; + } +}; + +/** + * API call for setting up the Knowledge Base. Provide a resource to set up a specific resource. + * + * @param {Object} options - The options object. + * @param {HttpSetup} options.http - HttpSetup + * @param {string} [options.resource] - Resource to be added to the KB, otherwise sets up the base KB + * @param {AbortSignal} [options.signal] - AbortSignal + * + * @returns {Promise} + */ +export const postKnowledgeBase = async ({ + http, + resource, + signal, +}: CreateKnowledgeBaseRequestParams & { + http: HttpSetup; + signal?: AbortSignal | undefined; +}): Promise => { + try { + const path = ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL.replace('{resource?}', resource || ''); + const response = await http.fetch(path, { + method: 'POST', + signal, + version: API_VERSIONS.internal.v1, + }); + + return response as CreateKnowledgeBaseResponse; + } catch (error) { + return error as IHttpFetchError; + } +}; + +/** + * API call for deleting the Knowledge Base. Provide a resource to delete that specific resource. + * + * @param {Object} options - The options object. + * @param {HttpSetup} options.http - HttpSetup + * @param {string} [options.resource] - Resource to be deleted from the KB, otherwise delete the entire KB + * @param {AbortSignal} [options.signal] - AbortSignal + * + * @returns {Promise} + */ +export const deleteKnowledgeBase = async ({ + http, + resource, + signal, +}: DeleteKnowledgeBaseRequestParams & { + http: HttpSetup; + signal?: AbortSignal | undefined; +}): Promise => { + try { + const path = ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL.replace('{resource?}', resource || ''); + const response = await http.fetch(path, { + method: 'DELETE', + signal, + version: API_VERSIONS.internal.v1, + }); + + return response as DeleteKnowledgeBaseResponse; + } catch (error) { + return error as IHttpFetchError; + } +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_create_knowledge_base_entry.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_create_knowledge_base_entry.tsx new file mode 100644 index 0000000000000..eaf9a32fde81a --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_create_knowledge_base_entry.tsx @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMutation } from '@tanstack/react-query'; +import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; +import type { IToasts } from '@kbn/core-notifications-browser'; +import { i18n } from '@kbn/i18n'; + +import { + API_VERSIONS, + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL, + KnowledgeBaseEntryCreateProps, + KnowledgeBaseEntryResponse, +} from '@kbn/elastic-assistant-common'; +import { useInvalidateKnowledgeBaseEntries } from './use_knowledge_base_entries'; + +const CREATE_KNOWLEDGE_BASE_ENTRY_MUTATION_KEY = [ + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL, + API_VERSIONS.internal.v1, +]; + +export interface UseCreateKnowledgeBaseEntryParams { + http: HttpSetup; + signal?: AbortSignal; + toasts?: IToasts; +} + +/** + * Hook for creating a Knowledge Base Entry + * + * @param {Object} options - The options object + * @param {HttpSetup} options.http - HttpSetup + * @param {AbortSignal} [options.signal] - AbortSignal + * @param {IToasts} [options.toasts] - IToasts + * + * @returns mutation hook for creating a Knowledge Base Entry + * + */ +export const useCreateKnowledgeBaseEntry = ({ + http, + signal, + toasts, +}: UseCreateKnowledgeBaseEntryParams) => { + const invalidateKnowledgeBaseEntries = useInvalidateKnowledgeBaseEntries(); + + return useMutation( + CREATE_KNOWLEDGE_BASE_ENTRY_MUTATION_KEY, + (entry: KnowledgeBaseEntryCreateProps) => { + return http.post( + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL, + { + body: JSON.stringify(entry), + version: API_VERSIONS.internal.v1, + signal, + } + ); + }, + { + onError: (error: IHttpFetchError) => { + if (error.name !== 'AbortError') { + toasts?.addError( + error.body && error.body.message ? new Error(error.body.message) : error, + { + title: i18n.translate( + 'xpack.elasticAssistant.knowledgeBase.entries.createErrorTitle', + { + defaultMessage: 'Error creating Knowledge Base Entry', + } + ), + } + ); + } + }, + onSettled: () => { + invalidateKnowledgeBaseEntries(); + }, + } + ); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_delete_knowledge_base_entries.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_delete_knowledge_base_entries.tsx new file mode 100644 index 0000000000000..0cfce8f576b24 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_delete_knowledge_base_entries.tsx @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMutation } from '@tanstack/react-query'; +import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; +import type { IToasts } from '@kbn/core-notifications-browser'; +import { i18n } from '@kbn/i18n'; + +import { + API_VERSIONS, + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION, + KnowledgeBaseEntryBulkActionBase, + KnowledgeBaseEntryBulkCrudActionResponse, + PerformKnowledgeBaseEntryBulkActionRequestBody, +} from '@kbn/elastic-assistant-common'; +import { useInvalidateKnowledgeBaseEntries } from './use_knowledge_base_entries'; + +const DELETE_KNOWLEDGE_BASE_ENTRIES_MUTATION_KEY = [ + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION, + API_VERSIONS.internal.v1, +]; + +export interface UseDeleteKnowledgeEntriesParams { + http: HttpSetup; + signal?: AbortSignal; + toasts?: IToasts; +} + +/** + * Hook for deleting Knowledge Base Entries by id or query. + * + * @param {Object} options - The options object + * @param {HttpSetup} options.http - HttpSetup + * @param {AbortSignal} [options.signal] - AbortSignal + * @param {IToasts} [options.toasts] - IToasts + * + * @returns mutation hook for deleting Knowledge Base Entries + * + */ +export const useDeleteKnowledgeBaseEntries = ({ + http, + signal, + toasts, +}: UseDeleteKnowledgeEntriesParams) => { + const invalidateKnowledgeBaseEntries = useInvalidateKnowledgeBaseEntries(); + + return useMutation( + DELETE_KNOWLEDGE_BASE_ENTRIES_MUTATION_KEY, + ({ ids, query }: KnowledgeBaseEntryBulkActionBase) => { + const body: PerformKnowledgeBaseEntryBulkActionRequestBody = { + delete: { + query, + ids, + }, + }; + return http.post( + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION, + { + body: JSON.stringify(body), + version: API_VERSIONS.internal.v1, + signal, + } + ); + }, + { + onError: (error: IHttpFetchError) => { + if (error.name !== 'AbortError') { + toasts?.addError( + error.body && error.body.message ? new Error(error.body.message) : error, + { + title: i18n.translate( + 'xpack.elasticAssistant.knowledgeBase.entries.deleteErrorTitle', + { + defaultMessage: 'Error deleting Knowledge Base Entries', + } + ), + } + ); + } + }, + onSettled: () => { + invalidateKnowledgeBaseEntries(); + }, + } + ); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_knowledge_base_entries.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_knowledge_base_entries.ts new file mode 100644 index 0000000000000..aa1d72d755ffa --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/entries/use_knowledge_base_entries.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { HttpSetup } from '@kbn/core/public'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { + API_VERSIONS, + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND, + FindKnowledgeBaseEntriesResponse, +} from '@kbn/elastic-assistant-common'; + +import { useCallback } from 'react'; + +export interface UseKnowledgeBaseEntriesParams { + http: HttpSetup; + signal?: AbortSignal | undefined; +} + +/** + * Hook for fetching Knowledge Base Entries. + * + * Note: RBAC is handled at kbDataClient layer, so unless user has KB feature privileges, this will only return system and their own user KB entries. + * + * @param {Object} options - The options object. + * @param {HttpSetup} options.http - HttpSetup + * @param {Function} [options.onFetch] - transformation function for kb entries fetch result + * @param {AbortSignal} [options.signal] - AbortSignal + * + * @returns {useQuery} hook for fetching Knowledge Base Entries + */ +const query = { + page: 1, + perPage: 100, +}; + +export const KNOWLEDGE_BASE_ENTRY_QUERY_KEY = [ + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND, + query.page, + query.perPage, + API_VERSIONS.internal.v1, +]; + +export const useKnowledgeBaseEntries = ({ http, signal }: UseKnowledgeBaseEntriesParams) => + useQuery( + KNOWLEDGE_BASE_ENTRY_QUERY_KEY, + async () => + http.fetch( + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND, + { + method: 'GET', + version: API_VERSIONS.internal.v1, + query, + signal, + } + ), + { + keepPreviousData: true, + initialData: { page: 1, perPage: 100, total: 0, data: [] }, + } + ); + +/** + * Use this hook to invalidate the Knowledge Base Entries cache. For example, adding, + * editing, or deleting any Knowledge Base entries should lead to cache invalidation. + * + * @returns {Function} - Function to invalidate the Knowledge Base Entries cache + */ +export const useInvalidateKnowledgeBaseEntries = () => { + const queryClient = useQueryClient(); + + return useCallback(() => { + queryClient.invalidateQueries(KNOWLEDGE_BASE_ENTRY_QUERY_KEY, { + refetchType: 'active', + }); + }, [queryClient]); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_delete_knowledge_base.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx similarity index 94% rename from x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_delete_knowledge_base.test.tsx rename to x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx index 06933c4ebeff9..b50c345edb3b3 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_delete_knowledge_base.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx @@ -7,14 +7,14 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { useDeleteKnowledgeBase, UseDeleteKnowledgeBaseParams } from './use_delete_knowledge_base'; -import { deleteKnowledgeBase as _deleteKnowledgeBase } from '../assistant/api'; +import { deleteKnowledgeBase as _deleteKnowledgeBase } from './api'; import { useMutation as _useMutation } from '@tanstack/react-query'; const useMutationMock = _useMutation as jest.Mock; const deleteKnowledgeBaseMock = _deleteKnowledgeBase as jest.Mock; -jest.mock('../assistant/api', () => { - const actual = jest.requireActual('../assistant/api'); +jest.mock('./api', () => { + const actual = jest.requireActual('./api'); return { ...actual, deleteKnowledgeBase: jest.fn((...args) => actual.deleteKnowledgeBase(...args)), diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_delete_knowledge_base.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.tsx similarity index 97% rename from x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_delete_knowledge_base.tsx rename to x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.tsx index 3266bc20b8cdd..5e4ce82bde3bd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_delete_knowledge_base.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.tsx @@ -9,7 +9,7 @@ import { useMutation } from '@tanstack/react-query'; import type { IToasts } from '@kbn/core-notifications-browser'; import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; import { i18n } from '@kbn/i18n'; -import { deleteKnowledgeBase } from '../assistant/api'; +import { deleteKnowledgeBase } from './api'; import { useInvalidateKnowledgeBaseStatus } from './use_knowledge_base_status'; const DELETE_KNOWLEDGE_BASE_MUTATION_KEY = ['elastic-assistant', 'delete-knowledge-base']; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_knowledge_base_status.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx similarity index 96% rename from x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_knowledge_base_status.test.tsx rename to x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx index a999666845378..aaad50afacd91 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_knowledge_base_status.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx @@ -7,12 +7,12 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { useKnowledgeBaseStatus, UseKnowledgeBaseStatusParams } from './use_knowledge_base_status'; -import { getKnowledgeBaseStatus as _getKnowledgeBaseStatus } from '../assistant/api'; +import { getKnowledgeBaseStatus as _getKnowledgeBaseStatus } from './api'; const getKnowledgeBaseStatusMock = _getKnowledgeBaseStatus as jest.Mock; -jest.mock('../assistant/api', () => { - const actual = jest.requireActual('../assistant/api'); +jest.mock('./api', () => { + const actual = jest.requireActual('./api'); return { ...actual, getKnowledgeBaseStatus: jest.fn((...args) => actual.getKnowledgeBaseStatus(...args)), diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_knowledge_base_status.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.tsx similarity index 97% rename from x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_knowledge_base_status.tsx rename to x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.tsx index c03eb31581e42..ba6317329d350 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_knowledge_base_status.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.tsx @@ -12,7 +12,7 @@ import type { IToasts } from '@kbn/core-notifications-browser'; import { i18n } from '@kbn/i18n'; import { useCallback } from 'react'; import { ReadKnowledgeBaseResponse } from '@kbn/elastic-assistant-common'; -import { getKnowledgeBaseStatus } from '../assistant/api'; +import { getKnowledgeBaseStatus } from './api'; const KNOWLEDGE_BASE_STATUS_QUERY_KEY = ['elastic-assistant', 'knowledge-base-status']; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_setup_knowledge_base.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx similarity index 94% rename from x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_setup_knowledge_base.test.tsx rename to x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx index 8e0b084e9beed..a252700ba744f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_setup_knowledge_base.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx @@ -7,13 +7,13 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { useSetupKnowledgeBase, UseSetupKnowledgeBaseParams } from './use_setup_knowledge_base'; -import { postKnowledgeBase as _postKnowledgeBase } from '../assistant/api'; +import { postKnowledgeBase as _postKnowledgeBase } from './api'; import { useMutation as _useMutation } from '@tanstack/react-query'; const postKnowledgeBaseMock = _postKnowledgeBase as jest.Mock; const useMutationMock = _useMutation as jest.Mock; -jest.mock('../assistant/api', () => { - const actual = jest.requireActual('../assistant/api'); +jest.mock('./api', () => { + const actual = jest.requireActual('./api'); return { ...actual, postKnowledgeBase: jest.fn((...args) => actual.postKnowledgeBase(...args)), diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_setup_knowledge_base.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.tsx similarity index 97% rename from x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_setup_knowledge_base.tsx rename to x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.tsx index 34533683e7921..c27c97976e989 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/use_setup_knowledge_base.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.tsx @@ -9,7 +9,7 @@ import { useMutation } from '@tanstack/react-query'; import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; import type { IToasts } from '@kbn/core-notifications-browser'; import { i18n } from '@kbn/i18n'; -import { postKnowledgeBase } from '../assistant/api'; +import { postKnowledgeBase } from './api'; import { useInvalidateKnowledgeBaseStatus } from './use_knowledge_base_status'; const SETUP_KNOWLEDGE_BASE_MUTATION_KEY = ['elastic-assistant', 'post-knowledge-base']; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/install_knowledge_base_button.tsx b/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/install_knowledge_base_button.tsx index f5a82fd02c55d..32e34eb59fa93 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/install_knowledge_base_button.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/install_knowledge_base_button.tsx @@ -10,8 +10,8 @@ import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useAssistantContext } from '../..'; -import { useSetupKnowledgeBase } from './use_setup_knowledge_base'; -import { useKnowledgeBaseStatus } from './use_knowledge_base_status'; +import { useSetupKnowledgeBase } from '../assistant/api/knowledge_base/use_setup_knowledge_base'; +import { useKnowledgeBaseStatus } from '../assistant/api/knowledge_base/use_knowledge_base_status'; const ESQL_RESOURCE = 'esql'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.test.tsx index 56f6796ac16fa..4d39504075c7e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.test.tsx @@ -11,7 +11,7 @@ import { fireEvent, render } from '@testing-library/react'; import { DEFAULT_LATEST_ALERTS } from '../assistant_context/constants'; import { KnowledgeBaseSettings } from './knowledge_base_settings'; import { TestProviders } from '../mock/test_providers/test_providers'; -import { useKnowledgeBaseStatus } from './use_knowledge_base_status'; +import { useKnowledgeBaseStatus } from '../assistant/api/knowledge_base/use_knowledge_base_status'; import { mockSystemPrompts } from '../mock/system_prompt'; import { defaultAssistantFeatures } from '@kbn/elastic-assistant-common'; @@ -47,7 +47,7 @@ const defaultProps = { setUpdatedKnowledgeBaseSettings, }; const mockDelete = jest.fn(); -jest.mock('./use_delete_knowledge_base', () => ({ +jest.mock('../assistant/api/knowledge_base/use_delete_knowledge_base', () => ({ useDeleteKnowledgeBase: jest.fn(() => { return { mutate: mockDelete, @@ -57,7 +57,7 @@ jest.mock('./use_delete_knowledge_base', () => ({ })); const mockSetup = jest.fn(); -jest.mock('./use_setup_knowledge_base', () => ({ +jest.mock('../assistant/api/knowledge_base/use_setup_knowledge_base', () => ({ useSetupKnowledgeBase: jest.fn(() => { return { mutate: mockSetup, @@ -66,7 +66,7 @@ jest.mock('./use_setup_knowledge_base', () => ({ }), })); -jest.mock('./use_knowledge_base_status', () => ({ +jest.mock('../assistant/api/knowledge_base/use_knowledge_base_status', () => ({ useKnowledgeBaseStatus: jest.fn(() => { return { data: { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.tsx index 8c83d1f3403e8..fc152d1e5a3da 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/knowledge_base/knowledge_base_settings.tsx @@ -30,9 +30,9 @@ import { AlertsSettings } from '../alerts/settings/alerts_settings'; import { useAssistantContext } from '../assistant_context'; import type { KnowledgeBaseConfig } from '../assistant/types'; import * as i18n from './translations'; -import { useDeleteKnowledgeBase } from './use_delete_knowledge_base'; -import { useKnowledgeBaseStatus } from './use_knowledge_base_status'; -import { useSetupKnowledgeBase } from './use_setup_knowledge_base'; +import { useDeleteKnowledgeBase } from '../assistant/api/knowledge_base/use_delete_knowledge_base'; +import { useKnowledgeBaseStatus } from '../assistant/api/knowledge_base/use_knowledge_base_status'; +import { useSetupKnowledgeBase } from '../assistant/api/knowledge_base/use_setup_knowledge_base'; const ESQL_RESOURCE = 'esql'; const KNOWLEDGE_BASE_INDEX_PATTERN_OLD = '.kibana-elastic-ai-assistant-kb'; diff --git a/x-pack/plugins/elastic_assistant/common/constants.ts b/x-pack/plugins/elastic_assistant/common/constants.ts index 5c5233eaaa6c8..d8c2630c1aef8 100755 --- a/x-pack/plugins/elastic_assistant/common/constants.ts +++ b/x-pack/plugins/elastic_assistant/common/constants.ts @@ -27,6 +27,9 @@ export const ANONYMIZATION_FIELDS_TABLE_MAX_PAGE_SIZE = 100; export const MAX_PROMPTS_TO_UPDATE_IN_PARALLEL = 50; export const PROMPTS_TABLE_MAX_PAGE_SIZE = 100; +// Knowledge Base +export const KNOWLEDGE_BASE_ENTRIES_TABLE_MAX_PAGE_SIZE = 100; + // Capabilities export const CAPABILITIES = `${BASE_PATH}/capabilities`; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts index 1e867ac4ae468..680ab17672f61 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts @@ -16,6 +16,7 @@ import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-ser import { KnowledgeBaseEntryCreateProps, KnowledgeBaseEntryResponse, + Metadata, } from '@kbn/elastic-assistant-common'; import pRetry from 'p-retry'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; @@ -221,12 +222,12 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient { /** * Adds LangChain Documents to the knowledge base * - * @param documents LangChain Documents to add to the knowledge base + * @param {Array>} documents - LangChain Documents to add to the knowledge base */ public addKnowledgeBaseDocuments = async ({ documents, }: { - documents: Document[]; + documents: Array>; }): Promise => { const writer = await this.getWriter(); const changedAt = new Date().toISOString(); @@ -240,9 +241,8 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient { const { errors, docs_created: docsCreated } = await writer.bulk({ documentsToCreate: documents.map((doc) => transformToCreateSchema(changedAt, this.spaceId, authenticatedUser, { - // TODO: Update the LangChain Document Metadata type extension metadata: { - kbResource: doc.metadata.kbResourcer ?? 'unknown', + kbResource: doc.metadata.kbResource ?? 'unknown', required: doc.metadata.required ?? false, source: doc.metadata.source ?? 'unknown', }, diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts index b34beb5c5aa9c..3d4666cdf7540 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts @@ -9,7 +9,9 @@ import { Logger } from '@kbn/core/server'; import { DirectoryLoader } from 'langchain/document_loaders/fs/directory'; import { TextLoader } from 'langchain/document_loaders/fs/text'; import { resolve } from 'path'; +import { Document } from 'langchain/document'; +import { Metadata } from '@kbn/elastic-assistant-common'; import { ElasticsearchStore } from '../elasticsearch_store/elasticsearch_store'; import { addRequiredKbResourceMetadata } from './add_required_kb_resource_metadata'; import { ESQL_RESOURCE } from '../../../routes/knowledge_base/constants'; @@ -47,15 +49,15 @@ export const loadESQL = async (esStore: ElasticsearchStore, logger: Logger): Pro true ); - const docs = await docsLoader.load(); - const languageDocs = await languageLoader.load(); + const docs = (await docsLoader.load()) as Array>; + const languageDocs = (await languageLoader.load()) as Array>; const rawExampleQueries = await exampleQueriesLoader.load(); // Add additional metadata to the example queries that indicates they are required KB documents: const requiredExampleQueries = addRequiredKbResourceMetadata({ docs: rawExampleQueries, kbResource: ESQL_RESOURCE, - }); + }) as Array>; logger.info( `Loading ${docs.length} ES|QL docs, ${languageDocs.length} language docs, and ${requiredExampleQueries.length} example queries into the Knowledge Base` diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts index b38d4b82f48b4..e45ad55999af6 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts @@ -25,6 +25,7 @@ import { KNOWLEDGE_BASE_EXECUTION_ERROR_EVENT, KNOWLEDGE_BASE_EXECUTION_SUCCESS_EVENT, } from '../../telemetry/event_based_telemetry'; +import { Metadata } from '@kbn/elastic-assistant-common'; jest.mock('uuid', () => ({ v4: jest.fn(), @@ -244,9 +245,9 @@ describe('ElasticsearchStore', () => { ], }); - const document = new Document({ + const document = new Document({ pageContent: 'interesting stuff', - metadata: { source: '1' }, + metadata: { kbResource: 'esql', required: false, source: '1' }, }); const docsInstalled = await esStore.addDocuments([document]); @@ -262,6 +263,8 @@ describe('ElasticsearchStore', () => { }, { metadata: { + kbResource: 'esql', + required: false, source: '1', }, text: 'interesting stuff', diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts index 86791cec5f5ce..e076c90526a53 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts @@ -17,6 +17,7 @@ import { Document } from 'langchain/document'; import { VectorStore } from '@langchain/core/vectorstores'; import * as uuid from 'uuid'; +import { Metadata } from '@kbn/elastic-assistant-common'; import { transformError } from '@kbn/securitysolution-es-utils'; import { ElasticsearchEmbeddings } from '../embeddings/elasticsearch_embeddings'; import { FlattenedHit, getFlattenedHits } from './helpers/get_flattened_hits'; @@ -105,7 +106,7 @@ export class ElasticsearchStore extends VectorStore { * @returns Promise of document IDs added to the store */ addDocuments = async ( - documents: Document[], + documents: Array>, options?: Record ): Promise => { // Code path for when `assistantKnowledgeBaseByDefault` FF is enabled @@ -145,7 +146,7 @@ export class ElasticsearchStore extends VectorStore { }; addDocumentsViaDataClient = async ( - documents: Document[], + documents: Array>, options?: Record ): Promise => { if (!this.kbDataClient) { diff --git a/x-pack/plugins/elastic_assistant/server/routes/helpers.ts b/x-pack/plugins/elastic_assistant/server/routes/helpers.ts index 932eafb4a549b..243de14d67ed3 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/helpers.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/helpers.ts @@ -5,11 +5,15 @@ * 2.0. */ -import { KibanaRequest } from '@kbn/core-http-server'; +import { IKibanaResponse, KibanaRequest, KibanaResponseFactory } from '@kbn/core-http-server'; import { Logger } from '@kbn/core/server'; import { Message, TraceData } from '@kbn/elastic-assistant-common'; import { ILicense } from '@kbn/licensing-plugin/server'; +import { AwaitedProperties } from '@kbn/utility-types'; +import { AssistantFeatureKey } from '@kbn/elastic-assistant-common/impl/capabilities'; import { MINIMUM_AI_ASSISTANT_LICENSE } from '../../common/constants'; +import { ElasticAssistantRequestHandlerContext } from '../types'; +import { buildResponse } from './utils'; interface GetPluginNameFromRequestParams { request: KibanaRequest; @@ -87,3 +91,69 @@ export const hasAIAssistantLicense = (license: ILicense): boolean => export const UPGRADE_LICENSE_MESSAGE = 'Your license does not support AI Assistant. Please upgrade your license.'; + +interface PerformChecksParams { + authenticatedUser?: boolean; + capability?: AssistantFeatureKey; + context: AwaitedProperties< + Pick + >; + license?: boolean; + request: KibanaRequest; + response: KibanaResponseFactory; +} + +/** + * Helper to perform checks for authenticated user, capability, and license. Perform all or one + * of the checks by providing relevant optional params. Check order is license, authenticated user, + * then capability. + * + * @param authenticatedUser - Whether to check for an authenticated user + * @param capability - Specific capability to check if enabled, e.g. `assistantModelEvaluation` + * @param context - Route context + * @param license - Whether to check for a valid license + * @param request - Route KibanaRequest + * @param response - Route KibanaResponseFactory + */ +export const performChecks = ({ + authenticatedUser, + capability, + context, + license, + request, + response, +}: PerformChecksParams): IKibanaResponse | undefined => { + const assistantResponse = buildResponse(response); + + if (license) { + if (!hasAIAssistantLicense(context.licensing.license)) { + return response.forbidden({ + body: { + message: UPGRADE_LICENSE_MESSAGE, + }, + }); + } + } + + if (authenticatedUser) { + if (context.elasticAssistant.getCurrentUser() == null) { + return assistantResponse.error({ + body: `Authenticated user not found`, + statusCode: 401, + }); + } + } + + if (capability) { + const pluginName = getPluginNameFromRequest({ + request, + defaultPluginName: DEFAULT_PLUGIN_NAME, + }); + const registeredFeatures = context.elasticAssistant.getRegisteredFeatures(pluginName); + if (!registeredFeatures[capability]) { + return response.notFound(); + } + } + + return undefined; +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/bulk_actions_route.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/bulk_actions_route.ts new file mode 100644 index 0000000000000..dbd9d83bae3ac --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/bulk_actions_route.ts @@ -0,0 +1,235 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; +import type { AuthenticatedUser, IKibanaResponse, KibanaResponseFactory } from '@kbn/core/server'; + +import { transformError } from '@kbn/securitysolution-es-utils'; +import { + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION, + PerformKnowledgeBaseEntryBulkActionRequestBody, + API_VERSIONS, + KnowledgeBaseEntryBulkCrudActionResults, + KnowledgeBaseEntryBulkCrudActionResponse, + KnowledgeBaseEntryBulkCrudActionSummary, + PerformKnowledgeBaseEntryBulkActionResponse, +} from '@kbn/elastic-assistant-common'; +import { buildRouteValidationWithZod } from '@kbn/elastic-assistant-common/impl/schemas/common'; + +import { performChecks } from '../../helpers'; +import { KNOWLEDGE_BASE_ENTRIES_TABLE_MAX_PAGE_SIZE } from '../../../../common/constants'; +import { EsKnowledgeBaseEntrySchema } from '../../../ai_assistant_data_clients/knowledge_base/types'; +import { ElasticAssistantPluginRouter } from '../../../types'; +import { buildResponse } from '../../utils'; +import { transformESSearchToKnowledgeBaseEntry } from '../../../ai_assistant_data_clients/knowledge_base/transforms'; +import { transformToCreateSchema } from '../../../ai_assistant_data_clients/knowledge_base/create_knowledge_base_entry'; + +export interface BulkOperationError { + message: string; + status?: number; + document: { + id: string; + name?: string; + }; +} + +export type BulkResponse = KnowledgeBaseEntryBulkCrudActionResults & { + errors?: BulkOperationError[]; +}; + +export type BulkActionError = BulkOperationError | unknown; + +const buildBulkResponse = ( + response: KibanaResponseFactory, + { + errors = [], + updated = [], + created = [], + deleted = [], + skipped = [], + }: KnowledgeBaseEntryBulkCrudActionResults & { errors: BulkOperationError[] } +): IKibanaResponse => { + const numSucceeded = updated.length + created.length + deleted.length; + const numSkipped = skipped.length; + const numFailed = errors.length; + + const summary: KnowledgeBaseEntryBulkCrudActionSummary = { + failed: numFailed, + succeeded: numSucceeded, + skipped: numSkipped, + total: numSucceeded + numFailed + numSkipped, + }; + + const results: KnowledgeBaseEntryBulkCrudActionResults = { + updated, + created, + deleted, + skipped, + }; + + if (numFailed > 0) { + return response.custom({ + headers: { 'content-type': 'application/json' }, + body: { + message: summary.succeeded > 0 ? 'Bulk edit partially failed' : 'Bulk edit failed', + attributes: { + errors: errors.map((e: BulkOperationError) => ({ + statusCode: e.status ?? 500, + knowledgeBaseEntries: [{ id: e.document.id, name: '' }], + message: e.message, + })), + results, + summary, + }, + }, + statusCode: 500, + }); + } + + const responseBody: KnowledgeBaseEntryBulkCrudActionResponse = { + success: true, + knowledgeBaseEntriesCount: summary.total, + attributes: { results, summary }, + }; + + return response.ok({ body: responseBody }); +}; + +export const bulkActionKnowledgeBaseEntriesRoute = (router: ElasticAssistantPluginRouter) => { + router.versioned + .post({ + access: 'internal', + path: ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_BULK_ACTION, + options: { + tags: ['access:elasticAssistant'], + timeout: { + idleSocket: moment.duration(15, 'minutes').asMilliseconds(), + }, + }, + }) + .addVersion( + { + version: API_VERSIONS.internal.v1, + validate: { + request: { + body: buildRouteValidationWithZod(PerformKnowledgeBaseEntryBulkActionRequestBody), + }, + }, + }, + async ( + context, + request, + response + ): Promise> => { + const assistantResponse = buildResponse(response); + try { + const ctx = await context.resolve(['core', 'elasticAssistant', 'licensing']); + const logger = ctx.elasticAssistant.logger; + + // Perform license, authenticated user and FF checks + const checkResponse = performChecks({ + authenticatedUser: true, + capability: 'assistantKnowledgeBaseByDefault', + context: ctx, + license: true, + request, + response, + }); + if (checkResponse) { + return checkResponse; + } + + logger.debug( + `Performing bulk action on Knowledge Base Entries:\n${JSON.stringify(request.body)}` + ); + + const { body } = request; + + const operationsCount = + (body?.update ? body.update?.length : 0) + + (body?.create ? body.create?.length : 0) + + (body?.delete ? body.delete?.ids?.length ?? 0 : 0); + if (operationsCount > KNOWLEDGE_BASE_ENTRIES_TABLE_MAX_PAGE_SIZE) { + return assistantResponse.error({ + body: `More than ${KNOWLEDGE_BASE_ENTRIES_TABLE_MAX_PAGE_SIZE} ids sent for bulk edit action.`, + statusCode: 400, + }); + } + + const abortController = new AbortController(); + + // subscribing to completed$, because it handles both cases when request was completed and aborted. + // when route is finished by timeout, aborted$ is not getting fired + request.events.completed$.subscribe(() => abortController.abort()); + const kbDataClient = await ctx.elasticAssistant.getAIAssistantKnowledgeBaseDataClient( + false + ); + const spaceId = ctx.elasticAssistant.getSpaceId(); + // Authenticated user null check completed in `performChecks()` above + const authenticatedUser = ctx.elasticAssistant.getCurrentUser() as AuthenticatedUser; + + if (body.create && body.create.length > 0) { + const result = await kbDataClient?.findDocuments({ + perPage: 100, + page: 1, + filter: `users:{ id: "${authenticatedUser?.profile_uid}" }`, + fields: [], + }); + if (result?.data != null && result.total > 0) { + return assistantResponse.error({ + statusCode: 409, + body: `Knowledge Base Entry id's: "${transformESSearchToKnowledgeBaseEntry( + result.data + ) + .map((c) => c.id) + .join(',')}" already exists`, + }); + } + } + + const writer = await kbDataClient?.getWriter(); + const changedAt = new Date().toISOString(); + const { + errors, + docs_created: docsCreated, + docs_updated: docsUpdated, + docs_deleted: docsDeleted, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + } = await writer!.bulk({ + documentsToCreate: body.create?.map((c) => + transformToCreateSchema(changedAt, spaceId, authenticatedUser, c) + ), + documentsToDelete: body.delete?.ids, + documentsToUpdate: [], // TODO: Support bulk update + authenticatedUser, + }); + const created = + docsCreated.length > 0 + ? await kbDataClient?.findDocuments({ + page: 1, + perPage: 100, + filter: docsCreated.map((c) => `_id:${c}`).join(' OR '), + }) + : undefined; + + return buildBulkResponse(response, { + // @ts-ignore-next-line TS2322 + updated: docsUpdated, + created: created?.data ? transformESSearchToKnowledgeBaseEntry(created?.data) : [], + deleted: docsDeleted ?? [], + errors, + }); + } catch (err) { + const error = transformError(err); + return assistantResponse.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/create_route.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/create_route.ts index 0c31974a20785..b93ab4e894c8b 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/create_route.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/create_route.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { IKibanaResponse } from '@kbn/core/server'; +import { IKibanaResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { API_VERSIONS, @@ -15,15 +15,17 @@ import { buildRouteValidationWithZod } from '@kbn/elastic-assistant-common/impl/ import { KnowledgeBaseEntryCreateProps, KnowledgeBaseEntryResponse, + Metadata, } from '@kbn/elastic-assistant-common/impl/schemas/knowledge_base/common_attributes.gen'; +import type { Document } from 'langchain/document'; import { ElasticAssistantPluginRouter } from '../../../types'; import { buildResponse } from '../../utils'; -import { UPGRADE_LICENSE_MESSAGE, hasAIAssistantLicense } from '../../helpers'; +import { performChecks } from '../../helpers'; export const createKnowledgeBaseEntryRoute = (router: ElasticAssistantPluginRouter): void => { router.versioned .post({ - access: 'public', + access: 'internal', path: ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL, options: { @@ -32,7 +34,7 @@ export const createKnowledgeBaseEntryRoute = (router: ElasticAssistantPluginRout }) .addVersion( { - version: API_VERSIONS.public.v1, + version: API_VERSIONS.internal.v1, validate: { request: { body: buildRouteValidationWithZod(KnowledgeBaseEntryCreateProps), @@ -43,27 +45,40 @@ export const createKnowledgeBaseEntryRoute = (router: ElasticAssistantPluginRout const assistantResponse = buildResponse(response); try { const ctx = await context.resolve(['core', 'elasticAssistant', 'licensing']); - const license = ctx.licensing.license; - if (!hasAIAssistantLicense(license)) { - return response.forbidden({ - body: { - message: UPGRADE_LICENSE_MESSAGE, - }, - }); + const logger = ctx.elasticAssistant.logger; + + // Perform license, authenticated user and FF checks + const checkResponse = performChecks({ + authenticatedUser: true, + capability: 'assistantKnowledgeBaseByDefault', + context: ctx, + license: true, + request, + response, + }); + if (checkResponse) { + return checkResponse; } - const authenticatedUser = ctx.elasticAssistant.getCurrentUser(); - if (authenticatedUser == null) { + logger.debug(`Creating KB Entry:\n${JSON.stringify(request.body)}`); + const documents: Array> = [ + { + metadata: request.body.metadata, + pageContent: request.body.text, + }, + ]; + const kbDataClient = await ctx.elasticAssistant.getAIAssistantKnowledgeBaseDataClient( + false + ); + const createResponse = await kbDataClient?.addKnowledgeBaseDocuments({ documents }); + + if (createResponse == null) { return assistantResponse.error({ - body: `Authenticated user not found`, - statusCode: 401, + body: `Knowledge Base Entry was not created`, + statusCode: 400, }); } - - return assistantResponse.error({ - body: `knowledge base entry was not created`, - statusCode: 400, - }); + return response.ok({ body: KnowledgeBaseEntryResponse.parse(createResponse[0]) }); } catch (err) { const error = transformError(err as Error); return assistantResponse.error({ diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/find_route.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/find_route.ts new file mode 100644 index 0000000000000..9dc7bb3f39dbf --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/find_route.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { IKibanaResponse } from '@kbn/core/server'; +import { transformError } from '@kbn/securitysolution-es-utils'; + +import { + API_VERSIONS, + ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND, + FindKnowledgeBaseEntriesRequestQuery, + FindKnowledgeBaseEntriesResponse, +} from '@kbn/elastic-assistant-common'; +import { buildRouteValidationWithZod } from '@kbn/elastic-assistant-common/impl/schemas/common'; +import { ElasticAssistantPluginRouter } from '../../../types'; +import { buildResponse } from '../../utils'; + +import { performChecks } from '../../helpers'; +import { transformESSearchToKnowledgeBaseEntry } from '../../../ai_assistant_data_clients/knowledge_base/transforms'; +import { EsKnowledgeBaseEntrySchema } from '../../../ai_assistant_data_clients/knowledge_base/types'; + +export const findKnowledgeBaseEntriesRoute = (router: ElasticAssistantPluginRouter) => { + router.versioned + .get({ + access: 'internal', + path: ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND, + options: { + tags: ['access:elasticAssistant'], + }, + }) + .addVersion( + { + version: API_VERSIONS.internal.v1, + validate: { + request: { + query: buildRouteValidationWithZod(FindKnowledgeBaseEntriesRequestQuery), + }, + }, + }, + async ( + context, + request, + response + ): Promise> => { + const assistantResponse = buildResponse(response); + try { + const { query } = request; + const ctx = await context.resolve(['core', 'elasticAssistant', 'licensing']); + + // Perform license, authenticated user and FF checks + const checkResponse = performChecks({ + authenticatedUser: true, + capability: 'assistantKnowledgeBaseByDefault', + context: ctx, + license: true, + request, + response, + }); + if (checkResponse) { + return checkResponse; + } + + const kbDataClient = await ctx.elasticAssistant.getAIAssistantKnowledgeBaseDataClient( + false + ); + const currentUser = ctx.elasticAssistant.getCurrentUser(); + + const additionalFilter = query.filter ? ` AND ${query.filter}` : ''; + const result = await kbDataClient?.findDocuments({ + perPage: query.per_page, + page: query.page, + sortField: query.sort_field, + sortOrder: query.sort_order, + filter: `users:{ id: "${currentUser?.profile_uid}" }${additionalFilter}`, // TODO: Update filter to include non-user system entries + fields: query.fields, + }); + + if (result) { + return response.ok({ + body: { + perPage: result.perPage, + page: result.page, + total: result.total, + data: transformESSearchToKnowledgeBaseEntry(result.data), + }, + }); + } + return response.ok({ + body: { perPage: query.per_page, page: query.page, data: [], total: 0 }, + }); + } catch (err) { + const error = transformError(err); + return assistantResponse.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts b/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts index fc0e30f4a925c..374b32d6cceb5 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts @@ -27,6 +27,9 @@ import { bulkPromptsRoute } from './prompts/bulk_actions_route'; import { findPromptsRoute } from './prompts/find_route'; import { bulkActionAnonymizationFieldsRoute } from './anonymization_fields/bulk_actions_route'; import { findAnonymizationFieldsRoute } from './anonymization_fields/find_route'; +import { bulkActionKnowledgeBaseEntriesRoute } from './knowledge_base/entries/bulk_actions_route'; +import { createKnowledgeBaseEntryRoute } from './knowledge_base/entries/create_route'; +import { findKnowledgeBaseEntriesRoute } from './knowledge_base/entries/find_route'; export const registerRoutes = ( router: ElasticAssistantPluginRouter, @@ -49,11 +52,16 @@ export const registerRoutes = ( // User Conversations search findUserConversationsRoute(router); - // Knowledge Base + // Knowledge Base Setup deleteKnowledgeBaseRoute(router); getKnowledgeBaseStatusRoute(router, getElserId); postKnowledgeBaseRoute(router, getElserId); + // Knowledge Base Entries + findKnowledgeBaseEntriesRoute(router); + createKnowledgeBaseEntryRoute(router); + bulkActionKnowledgeBaseEntriesRoute(router); + // Actions Connector Execute (LLM Wrapper) postActionsConnectorExecuteRoute(router, getElserId); From ff19b297fb80af793919c71c2eb883406c9039c3 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 03:00:15 +0100 Subject: [PATCH 095/127] skip flaky suite (#186438) --- .../pages/cis_integrations/cspm/cis_integration_aws.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_aws.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_aws.ts index 2dd8f36af154d..cae23e9bfe8a4 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_aws.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_aws.ts @@ -38,7 +38,8 @@ export default function (providerContext: FtrProviderContext) { await cisIntegration.navigateToAddIntegrationCspmPage(); }); - describe('CIS_AWS Organization Cloud Formation', () => { + // FLAKY: https://github.com/elastic/kibana/issues/186438 + describe.skip('CIS_AWS Organization Cloud Formation', () => { it('Initial form state, AWS Org account, and CloudFormation should be selected by default', async () => { expect((await cisIntegration.isRadioButtonChecked('cloudbeat/cis_aws')) === true); expect((await cisIntegration.isRadioButtonChecked('organization-account')) === true); From c4cd3ab8d39da46bc4047427507eb4a5d9ad1c52 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 19 Jun 2024 03:02:16 +0100 Subject: [PATCH 096/127] skip flaky suite (#176335) --- .../user_profiles/use_bulk_get_user_profiles.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts index 1574c1ddd2580..5732085d99c8e 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts @@ -19,7 +19,8 @@ jest.mock('./api'); const useKibanaMock = useKibana as jest.Mock; -describe('useBulkGetUserProfiles', () => { +// FLAKY: https://github.com/elastic/kibana/issues/176335 +describe.skip('useBulkGetUserProfiles', () => { const props = { uids: userProfilesIds, }; From 2a6172c090ba29416f01264be32d0af469c29965 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 19 Jun 2024 07:00:55 +0200 Subject: [PATCH 097/127] [api-docs] 2024-06-19 Daily api_docs build (#186441) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/742 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- .../ai_assistant_management_selection.mdx | 2 +- api_docs/aiops.devdocs.json | 8 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/apm_data_access.mdx | 2 +- api_docs/asset_manager.mdx | 2 +- api_docs/assets_data_access.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 4 +- api_docs/data_quality.mdx | 2 +- api_docs/data_query.mdx | 4 +- api_docs/data_search.devdocs.json | 128 + api_docs/data_search.mdx | 4 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/dataset_quality.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 4 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.devdocs.json | 18 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/discover_shared.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/elastic_assistant.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/esql_data_grid.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_annotation_listing.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/fields_metadata.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 25 +- api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/ingest_pipelines.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/integration_assistant.devdocs.json | 2417 ++++-- api_docs/integration_assistant.mdx | 11 +- api_docs/interactive_setup.mdx | 2 +- api_docs/investigate.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_actions_types.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_log_pattern_analysis.mdx | 2 +- api_docs/kbn_aiops_log_rate_analysis.mdx | 2 +- .../kbn_alerting_api_integration_helpers.mdx | 2 +- api_docs/kbn_alerting_comparators.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerting_types.mdx | 2 +- .../kbn_alerts_as_data_utils.devdocs.json | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_collection_utils.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_data_view.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_bfetch_error.mdx | 2 +- api_docs/kbn_calculate_auto.mdx | 2 +- .../kbn_calculate_width_from_char_count.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mock.mdx | 2 +- api_docs/kbn_code_owners.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.devdocs.json | 7036 +++++++++++++++-- api_docs/kbn_config_schema.mdx | 4 +- ...ent_management_content_editor.devdocs.json | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...gement_table_list_view_common.devdocs.json | 28 + ...tent_management_table_list_view_common.mdx | 4 +- ...ntent_management_table_list_view_table.mdx | 2 +- ...tent_management_user_profiles.devdocs.json | 622 ++ .../kbn_content_management_user_profiles.mdx | 33 + api_docs/kbn_content_management_utils.mdx | 2 +- .../kbn_core_analytics_browser.devdocs.json | 3186 +++++++- api_docs/kbn_core_analytics_browser.mdx | 4 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- .../kbn_core_analytics_server.devdocs.json | 3197 +++++++- api_docs/kbn_core_analytics_server.mdx | 7 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- ...bn_core_apps_browser_internal.devdocs.json | 8 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.devdocs.json | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- ...e_http_router_server_internal.devdocs.json | 20 +- .../kbn_core_http_router_server_internal.mdx | 2 +- ...core_http_router_server_mocks.devdocs.json | 4 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.devdocs.json | 92 +- api_docs/kbn_core_http_server.mdx | 4 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- .../kbn_core_lifecycle_browser.devdocs.json | 36 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- .../kbn_core_lifecycle_server.devdocs.json | 64 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- .../kbn_core_plugins_contracts_browser.mdx | 2 +- .../kbn_core_plugins_contracts_server.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_security_browser.mdx | 2 +- .../kbn_core_security_browser_internal.mdx | 2 +- api_docs/kbn_core_security_browser_mocks.mdx | 2 +- api_docs/kbn_core_security_common.mdx | 2 +- api_docs/kbn_core_security_server.mdx | 2 +- .../kbn_core_security_server_internal.mdx | 2 +- api_docs/kbn_core_security_server_mocks.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- ...n_core_status_server_internal.devdocs.json | 28 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- .../kbn_core_test_helpers_model_versions.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_browser.mdx | 2 +- ...kbn_core_user_profile_browser_internal.mdx | 2 +- .../kbn_core_user_profile_browser_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_common.mdx | 2 +- api_docs/kbn_core_user_profile_server.mdx | 2 +- .../kbn_core_user_profile_server_internal.mdx | 2 +- .../kbn_core_user_profile_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_custom_icons.mdx | 2 +- api_docs/kbn_custom_integrations.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_forge.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_data_stream_adapter.mdx | 2 +- api_docs/kbn_data_view_utils.devdocs.json | 69 +- api_docs/kbn_data_view_utils.mdx | 7 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_fleet.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_deeplinks_security.devdocs.json | 4 +- api_docs/kbn_deeplinks_security.mdx | 2 +- api_docs/kbn_deeplinks_shared.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.devdocs.json | 96 + api_docs/kbn_discover_utils.mdx | 4 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt.devdocs.json | 4130 ++++++++++ api_docs/kbn_ebt.mdx | 36 + api_docs/kbn_ebt_tools.devdocs.json | 16 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_agent_utils.mdx | 2 +- api_docs/kbn_elastic_assistant.mdx | 2 +- .../kbn_elastic_assistant_common.devdocs.json | 155 +- api_docs/kbn_elastic_assistant_common.mdx | 4 +- api_docs/kbn_entities_schema.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_esql_ast.devdocs.json | 14 +- api_docs/kbn_esql_ast.mdx | 4 +- api_docs/kbn_esql_utils.mdx | 2 +- ..._esql_validation_autocomplete.devdocs.json | 500 +- api_docs/kbn_esql_validation_autocomplete.mdx | 4 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_field_utils.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_formatters.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- .../kbn_ftr_common_functional_ui_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_grouping.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_index_management.mdx | 2 +- api_docs/kbn_inference_integration_flyout.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_ipynb.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_lens_embeddable_utils.mdx | 2 +- api_docs/kbn_lens_formula_docs.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_content_badge.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- .../kbn_management_settings_application.mdx | 2 +- ...ent_settings_components_field_category.mdx | 2 +- ...gement_settings_components_field_input.mdx | 2 +- ...nagement_settings_components_field_row.mdx | 2 +- ...bn_management_settings_components_form.mdx | 2 +- ...n_management_settings_field_definition.mdx | 2 +- api_docs/kbn_management_settings_ids.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_settings_types.mdx | 2 +- .../kbn_management_settings_utilities.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.devdocs.json | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_cancellable_search.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- api_docs/kbn_ml_chi2test.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_in_memory_table.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_time_buckets.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_ui_actions.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_mock_idp_utils.mdx | 2 +- api_docs/kbn_monaco.devdocs.json | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- .../kbn_observability_alerting_test_data.mdx | 2 +- ...ility_get_padded_alert_time_range_util.mdx | 2 +- api_docs/kbn_openapi_bundler.mdx | 2 +- api_docs/kbn_openapi_generator.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- api_docs/kbn_panel_loader.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_check.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_presentation_containers.mdx | 2 +- api_docs/kbn_presentation_publishing.mdx | 2 +- api_docs/kbn_profiling_utils.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_react_hooks.mdx | 2 +- api_docs/kbn_react_kibana_context_common.mdx | 2 +- api_docs/kbn_react_kibana_context_render.mdx | 2 +- api_docs/kbn_react_kibana_context_root.mdx | 2 +- api_docs/kbn_react_kibana_context_styled.mdx | 2 +- api_docs/kbn_react_kibana_context_theme.mdx | 2 +- api_docs/kbn_react_kibana_mount.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_reporting_csv_share_panel.mdx | 2 +- api_docs/kbn_reporting_export_types_csv.mdx | 2 +- .../kbn_reporting_export_types_csv_common.mdx | 2 +- api_docs/kbn_reporting_export_types_pdf.mdx | 2 +- .../kbn_reporting_export_types_pdf_common.mdx | 2 +- api_docs/kbn_reporting_export_types_png.mdx | 2 +- .../kbn_reporting_export_types_png_common.mdx | 2 +- api_docs/kbn_reporting_mocks_server.mdx | 2 +- api_docs/kbn_reporting_public.mdx | 2 +- api_docs/kbn_reporting_server.mdx | 2 +- api_docs/kbn_resizable_layout.mdx | 2 +- .../kbn_response_ops_feature_flag_service.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_router_to_openapispec.mdx | 2 +- api_docs/kbn_router_utils.mdx | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_search_api_panels.mdx | 2 +- api_docs/kbn_search_connectors.devdocs.json | 14 +- api_docs/kbn_search_connectors.mdx | 2 +- api_docs/kbn_search_errors.mdx | 2 +- api_docs/kbn_search_index_documents.mdx | 2 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_search_types.mdx | 2 +- api_docs/kbn_security_hardening.mdx | 2 +- api_docs/kbn_security_plugin_types_common.mdx | 2 +- api_docs/kbn_security_plugin_types_public.mdx | 2 +- api_docs/kbn_security_plugin_types_server.mdx | 2 +- api_docs/kbn_security_solution_features.mdx | 2 +- api_docs/kbn_security_solution_navigation.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_serverless_common_settings.mdx | 2 +- .../kbn_serverless_observability_settings.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_search_settings.mdx | 2 +- api_docs/kbn_serverless_security_settings.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_error_boundary.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_tabbed_modal.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_predicates.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_eui_helpers.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_timerange.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_triggers_actions_ui_types.mdx | 2 +- api_docs/kbn_try_in_console.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.devdocs.json | 11 - api_docs/kbn_ui_shared_deps_src.mdx | 4 +- api_docs/kbn_ui_theme.devdocs.json | 12 - api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_data_table.mdx | 2 +- api_docs/kbn_unified_doc_viewer.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_unsaved_changes_badge.mdx | 2 +- api_docs/kbn_unsaved_changes_prompt.mdx | 2 +- api_docs/kbn_use_tracked_promise.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_visualization_utils.mdx | 2 +- api_docs/kbn_xstate_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kbn_zod_helpers.devdocs.json | 43 + api_docs/kbn_zod_helpers.mdx | 4 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/links.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/logs_data_access.mdx | 2 +- api_docs/logs_explorer.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/metrics_data_access.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/mock_idp_plugin.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/no_data_page.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.devdocs.json | 4 +- api_docs/observability.mdx | 2 +- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_a_i_assistant_app.mdx | 2 +- .../observability_ai_assistant_management.mdx | 2 +- api_docs/observability_logs_explorer.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/painless_lab.mdx | 2 +- api_docs/plugin_directory.mdx | 43 +- api_docs/presentation_panel.mdx | 2 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/profiling_data_access.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/search_connectors.mdx | 2 +- api_docs/search_inference_endpoints.mdx | 2 +- api_docs/search_notebooks.mdx | 2 +- api_docs/search_playground.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.devdocs.json | 12 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/slo.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.devdocs.json | 37 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.devdocs.json | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/text_based_languages.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_doc_viewer.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.devdocs.json | 8 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/uptime.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.devdocs.json | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 736 files changed, 20759 insertions(+), 2844 deletions(-) create mode 100644 api_docs/kbn_content_management_user_profiles.devdocs.json create mode 100644 api_docs/kbn_content_management_user_profiles.mdx create mode 100644 api_docs/kbn_ebt.devdocs.json create mode 100644 api_docs/kbn_ebt.mdx diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 624022104e4b5..246481da11766 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: 2024-06-18 +date: 2024-06-19 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 779596da4321e..467d9cf5a7b1f 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index 48d70e70a5982..e2ebb27cfb3f1 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.devdocs.json b/api_docs/aiops.devdocs.json index 0f81782c4ed41..5d8cd183f7416 100644 --- a/api_docs/aiops.devdocs.json +++ b/api_docs/aiops.devdocs.json @@ -242,9 +242,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -252,9 +252,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 6589c58e34397..f5e85bf416a3c 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: 2024-06-18 +date: 2024-06-19 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 a158e8daac03a..174daf92bb302 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: 2024-06-18 +date: 2024-06-19 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 aa4431dbb04da..d9ccc16a8acb4 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 3e2cc9fefafc0..cf0bc62f7d985 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 2d1ba34fc9aaa..64cfd25389da0 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/assets_data_access.mdx b/api_docs/assets_data_access.mdx index 3ee0d44d975bd..76dad9651578f 100644 --- a/api_docs/assets_data_access.mdx +++ b/api_docs/assets_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetsDataAccess title: "assetsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the assetsDataAccess plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetsDataAccess'] --- import assetsDataAccessObj from './assets_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index fb0a9a20e575c..4c8b9bbe19251 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: 2024-06-18 +date: 2024-06-19 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 393d71d9328ce..7d4dd4fd3ca99 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: 2024-06-18 +date: 2024-06-19 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 7c71ac4bfb55e..91e867a7999af 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: 2024-06-18 +date: 2024-06-19 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 c29e6f64f1930..2beb8d47c6930 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: 2024-06-18 +date: 2024-06-19 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 ca4066e185d27..7f1e24b9fea6d 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: 2024-06-18 +date: 2024-06-19 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 b1e7c01136a03..190013ec6c9cf 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 69ff8dc302a53..bb3b69a7c63f1 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: 2024-06-18 +date: 2024-06-19 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 79bf2006480fd..2d88f69aeec5c 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: 2024-06-18 +date: 2024-06-19 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 e540ca3c9d751..daf262ab94138 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: 2024-06-18 +date: 2024-06-19 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 307768caee6aa..a812d76502208 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: 2024-06-18 +date: 2024-06-19 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 31535c63a5280..8b056c595d8d8 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: 2024-06-18 +date: 2024-06-19 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 51ec36c9a0e93..a061227fb6cae 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: 2024-06-18 +date: 2024-06-19 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 61fad6567819c..97ce881289142 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: 2024-06-18 +date: 2024-06-19 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 55e65c72384d8..aef3f276d8a1c 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: 2024-06-18 +date: 2024-06-19 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 dd62d55494171..96515a7692a6c 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: 2024-06-18 +date: 2024-06-19 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 d2b741e32aed6..119f9b57bf172 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index b8bd937dbe6c2..4bc38d07ab1b5 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3194 | 31 | 2585 | 24 | +| 3199 | 31 | 2590 | 24 | ## Client diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx index 4d138efed58ae..c9508d873d3ce 100644 --- a/api_docs/data_quality.mdx +++ b/api_docs/data_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality title: "dataQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the dataQuality plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality'] --- import dataQualityObj from './data_quality.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index ff7b36e487175..3123c6516428a 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3194 | 31 | 2585 | 24 | +| 3199 | 31 | 2590 | 24 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index a9e4a675758c1..3e3047831b93f 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -16864,6 +16864,134 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "data", + "id": "def-common.queryToFields", + "type": "Function", + "tags": [], + "label": "queryToFields", + "description": [], + "signature": [ + "({\n dataView,\n sort,\n request,\n}: { dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewLazy", + "text": "DataViewLazy" + }, + "; sort?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.EsQuerySortValue", + "text": "EsQuerySortValue" + }, + " | ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.EsQuerySortValue", + "text": "EsQuerySortValue" + }, + "[] | undefined; request: ", + "SearchRequest", + "; }) => Promise>" + ], + "path": "src/plugins/data/common/search/search_source/query_to_fields.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.queryToFields.$1", + "type": "Object", + "tags": [], + "label": "{\n dataView,\n sort,\n request,\n}", + "description": [], + "path": "src/plugins/data/common/search/search_source/query_to_fields.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.queryToFields.$1.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewLazy", + "text": "DataViewLazy" + } + ], + "path": "src/plugins/data/common/search/search_source/query_to_fields.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-common.queryToFields.$1.sort", + "type": "CompoundType", + "tags": [], + "label": "sort", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.EsQuerySortValue", + "text": "EsQuerySortValue" + }, + " | ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.EsQuerySortValue", + "text": "EsQuerySortValue" + }, + "[] | undefined" + ], + "path": "src/plugins/data/common/search/search_source/query_to_fields.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-common.queryToFields.$1.request", + "type": "Object", + "tags": [], + "label": "request", + "description": [], + "signature": [ + "{ [x: string]: any; }" + ], + "path": "src/plugins/data/common/search/search_source/query_to_fields.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "data", "id": "def-common.splitStringInterval", diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 066c7271b7b52..181a37757cacb 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3194 | 31 | 2585 | 24 | +| 3199 | 31 | 2590 | 24 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 296636689811f..3af5d0fe9268a 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: 2024-06-18 +date: 2024-06-19 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 94ebc7428bc25..206f19c400122 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: 2024-06-18 +date: 2024-06-19 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 4cc110a02ed31..b7a04fc6457ca 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 23caaad9e7d54..74c481eaad31c 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: 2024-06-18 +date: 2024-06-19 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 f30163d4e24d1..d432893bc384f 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 7f3ddaf93dd5e..9be5bb8dcf960 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index c810331094fbb..5c6f96d6421d7 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 7f17da6336fad..4752ee8c2b541 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -360,7 +360,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/console/theme.ts#:~:text=darkMode), [theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/console/theme.ts#:~:text=darkMode) | - | +| | [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [esql_theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/esql/lib/esql_theme.ts#:~:text=darkMode), [theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/console/theme.ts#:~:text=darkMode), [theme.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-monaco/src/console/theme.ts#:~:text=darkMode) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 73a33c4668a80..c99f47c97e352 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 953a9839ff37a..35498a89f5b17 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index 1e2946e6fa780..26f8c41e05c83 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -1707,7 +1707,7 @@ "tags": [], "label": "DiscoverSetup", "description": [], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -1730,7 +1730,7 @@ }, " | undefined" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false }, @@ -1744,7 +1744,7 @@ "signature": [ "() => void" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false, "children": [], @@ -1760,7 +1760,7 @@ "signature": [ "(projectNavId: string, options: { enabled: boolean; showLogsExplorerTabs: boolean; }) => void" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -1774,7 +1774,7 @@ "signature": [ "string" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -1789,7 +1789,7 @@ "signature": [ "{ enabled: boolean; showLogsExplorerTabs: boolean; }" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -1808,7 +1808,7 @@ "tags": [], "label": "DiscoverStart", "description": [], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -1831,7 +1831,7 @@ }, " | undefined" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false }, @@ -1861,7 +1861,7 @@ }, ">" ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/types.ts", "deprecated": false, "trackAdoption": false } diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index e364ccc82a307..64e53552a24f3 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: 2024-06-18 +date: 2024-06-19 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 c77515d70677e..5583e7fac0809 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx index 915e355fd79e4..00441fc0a8e03 100644 --- a/api_docs/discover_shared.mdx +++ b/api_docs/discover_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared title: "discoverShared" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverShared plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared'] --- import discoverSharedObj from './discover_shared.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 1a6f9e9575cd9..04dbf12c64752 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index 441403cde9067..2d685a960e6cc 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 76871e6e68083..6a9cebf1365b0 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: 2024-06-18 +date: 2024-06-19 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 e04871b3b1db9..345548c4b57bf 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: 2024-06-18 +date: 2024-06-19 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 8d9ac94478971..e9373181cd163 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: 2024-06-18 +date: 2024-06-19 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 1f3003a64cb9b..c9eee95cb72b9 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: 2024-06-18 +date: 2024-06-19 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 8108a8b6776ee..e831609643e15 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index 529e5bfc24b8c..bd96bca5d8a5e 100644 --- a/api_docs/esql_data_grid.mdx +++ b/api_docs/esql_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esqlDataGrid title: "esqlDataGrid" image: https://source.unsplash.com/400x175/?github description: API docs for the esqlDataGrid plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esqlDataGrid'] --- import esqlDataGridObj from './esql_data_grid.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 1c9e14ba90492..0f7fd892c5e5c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index d45db1f6914e6..025991c1fda51 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index da36e99e65ca2..f1ae9dc895fd4 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 0025d08edc171..81c45d0084cff 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 01eafa01dee30..6359145989bed 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: 2024-06-18 +date: 2024-06-19 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 925852e77d69b..88e7721ea46a3 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: 2024-06-18 +date: 2024-06-19 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 8aa5f4462cf5f..ce962310cffe1 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: 2024-06-18 +date: 2024-06-19 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 bba400d1b3045..0dbd83678d813 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: 2024-06-18 +date: 2024-06-19 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 1a303f42e9638..f4b89b2c1e8fb 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: 2024-06-18 +date: 2024-06-19 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 0ffcf4d1ee5bd..13f027fff7e22 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: 2024-06-18 +date: 2024-06-19 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 305b36fdb6207..f86f46f96ef8a 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: 2024-06-18 +date: 2024-06-19 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 0cbea72f7563c..b13293aeedd00 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: 2024-06-18 +date: 2024-06-19 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 c35b81f908315..06fbe7aea3fe6 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: 2024-06-18 +date: 2024-06-19 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 78a57072b2ae2..896a29a9180ed 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: 2024-06-18 +date: 2024-06-19 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 3fa4ac3f62b0f..5f99e621e1423 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: 2024-06-18 +date: 2024-06-19 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 4452aa394f13c..b81f4fdee7ec1 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: 2024-06-18 +date: 2024-06-19 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 626bd0655b3dc..0eae0e2e002e7 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: 2024-06-18 +date: 2024-06-19 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 ad99535b03f13..0427130b0f0bf 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: 2024-06-18 +date: 2024-06-19 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 a319f1537ccf5..bc5f7857bcc3c 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: 2024-06-18 +date: 2024-06-19 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 bb88bdc3705a7..8a1e28a04bf08 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/fields_metadata.mdx b/api_docs/fields_metadata.mdx index ce996ad370aa5..4216234eb614b 100644 --- a/api_docs/fields_metadata.mdx +++ b/api_docs/fields_metadata.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldsMetadata title: "fieldsMetadata" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldsMetadata plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldsMetadata'] --- import fieldsMetadataObj from './fields_metadata.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 790b8fc5cff15..260ec37968424 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: 2024-06-18 +date: 2024-06-19 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 a2fd13d1c9964..b652e97a9a80c 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: 2024-06-18 +date: 2024-06-19 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 5147aec2df8ab..a557fd5e66e8a 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index eccb9aef35f1b..9106288513ae1 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -6349,7 +6349,7 @@ "section": "def-common.SavedObjectsClientContract", "text": "SavedObjectsClientContract" }, - ", ids: string[], options?: { fields?: string[] | undefined; withPackagePolicies?: boolean | undefined; ignoreMissing?: boolean | undefined; }) => Promise<", + ", ids: (string | { id: string; spaceId?: string | undefined; })[], options?: { fields?: string[] | undefined; withPackagePolicies?: boolean | undefined; ignoreMissing?: boolean | undefined; }) => Promise<", { "pluginId": "fleet", "scope": "common", @@ -6392,7 +6392,7 @@ "label": "ids", "description": [], "signature": [ - "string[]" + "(string | { id: string; spaceId?: string | undefined; })[]" ], "path": "x-pack/plugins/fleet/server/services/agent_policy.ts", "deprecated": false, @@ -9915,7 +9915,7 @@ "section": "def-common.ListWithKuery", "text": "ListWithKuery" }, - ") => Promise<", + " & { spaceId?: string | undefined; }) => Promise<", { "pluginId": "fleet", "scope": "common", @@ -9961,7 +9961,7 @@ { "parentPluginId": "fleet", "id": "def-server.PackagePolicyClient.list.$2", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "options", "description": [], @@ -9972,7 +9972,8 @@ "docId": "kibFleetPluginApi", "section": "def-common.ListWithKuery", "text": "ListWithKuery" - } + }, + " & { spaceId?: string | undefined; }" ], "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", "deprecated": false, @@ -23986,6 +23987,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.PackagePolicy.spaceId", + "type": "string", + "tags": [], + "label": "spaceId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.PackagePolicy.inputs", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 75c84f6c1d72b..3730f61af825b 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1338 | 5 | 1216 | 72 | +| 1339 | 5 | 1217 | 72 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 215446f0c0bb3..627f17964ac92 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: 2024-06-18 +date: 2024-06-19 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 a86418e1b03d6..0a2c709cc164a 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: 2024-06-18 +date: 2024-06-19 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 d08cb4c662cf9..899804f8cf78e 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: 2024-06-18 +date: 2024-06-19 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 1025665cd37ed..7557dc6075977 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: 2024-06-18 +date: 2024-06-19 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 03bb198df26a7..a4fc0e4c26f98 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: 2024-06-18 +date: 2024-06-19 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 1942fce8dc4b3..cf7e4b6bd480a 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: 2024-06-18 +date: 2024-06-19 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 adf5bec595e95..911075f5d65a2 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index fbf0e38e34f54..4a0a9592144b9 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 14af91942d5bb..ebe749551fc4d 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/integration_assistant.devdocs.json b/api_docs/integration_assistant.devdocs.json index d5c5221c93afa..94182a303ea0f 100644 --- a/api_docs/integration_assistant.devdocs.json +++ b/api_docs/integration_assistant.devdocs.json @@ -47,873 +47,316 @@ "common": { "classes": [], "functions": [], - "interfaces": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.BuildIntegrationApiRequest", - "type": "Interface", - "tags": [], - "label": "BuildIntegrationApiRequest", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.BuildIntegrationApiRequest.integration", - "type": "Object", - "tags": [], - "label": "integration", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.Integration", - "text": "Integration" - } - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, + "interfaces": [], + "enums": [], + "misc": [ { "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiRequest", - "type": "Interface", + "id": "def-common.BuildIntegrationRequestBody", + "type": "Type", "tags": [], - "label": "CategorizationApiRequest", + "label": "BuildIntegrationRequestBody", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiRequest.packageName", - "type": "string", - "tags": [], - "label": "packageName", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, + "signature": [ + "{ integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiRequest.dataStreamName", - "type": "string", - "tags": [], - "label": "dataStreamName", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiRequest.rawSamples", - "type": "Array", - "tags": [], - "label": "rawSamples", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiRequest.currentPipeline", - "type": "Uncategorized", - "tags": [], - "label": "currentPipeline", - "description": [], - "signature": [ - "object" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }; }" ], + "path": "x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiResponse", - "type": "Interface", + "id": "def-common.CATEGORIZATION_GRAPH_PATH", + "type": "string", "tags": [], - "label": "CategorizationApiResponse", + "label": "CATEGORIZATION_GRAPH_PATH", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", + "path": "x-pack/plugins/integration_assistant/common/constants.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.CategorizationApiResponse.results", - "type": "Object", - "tags": [], - "label": "results", - "description": [], - "signature": [ - "{ pipeline: object; docs: object[]; }" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream", - "type": "Interface", + "id": "def-common.CategorizationRequestBody", + "type": "Type", "tags": [], - "label": "DataStream", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.name", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.description", - "type": "string", - "tags": [], - "label": "description", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.inputTypes", - "type": "Array", - "tags": [], - "label": "inputTypes", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.InputTypes", - "text": "InputTypes" - }, - "[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.rawSamples", - "type": "Array", - "tags": [], - "label": "rawSamples", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.pipeline", - "type": "Uncategorized", - "tags": [], - "label": "pipeline", - "description": [], - "signature": [ - "object" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.DataStream.docs", - "type": "Array", - "tags": [], - "label": "docs", - "description": [], - "signature": [ - "object[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiRequest", - "type": "Interface", - "tags": [], - "label": "EcsMappingApiRequest", + "label": "CategorizationRequestBody", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiRequest.packageName", - "type": "string", - "tags": [], - "label": "packageName", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, + "signature": [ + "{ connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; currentPipeline: { processors: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiRequest.dataStreamName", - "type": "string", - "tags": [], - "label": "dataStreamName", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiRequest.rawSamples", - "type": "Array", - "tags": [], - "label": "rawSamples", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiRequest.mapping", - "type": "Uncategorized", - "tags": [], - "label": "mapping", - "description": [], - "signature": [ - "object | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "[] | undefined; }; }" ], - "initialIsOpen": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiResponse", - "type": "Interface", - "tags": [], - "label": "EcsMappingApiResponse", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", + "path": "x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.EcsMappingApiResponse.results", - "type": "Object", - "tags": [], - "label": "results", - "description": [], - "signature": [ - "{ mapping: object; pipeline: object; }" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorItem", - "type": "Interface", + "id": "def-common.CategorizationResponse", + "type": "Type", "tags": [], - "label": "ESProcessorItem", + "label": "CategorizationResponse", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "signature": [ + "{ results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorItem.Unnamed", - "type": "IndexSignature", - "tags": [], - "label": "[processorName: string]: ESProcessorOptions", - "description": [], - "signature": [ - "[processorName: string]: ", - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.ESProcessorOptions", - "text": "ESProcessorOptions" - } - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }; }" ], + "path": "x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions", - "type": "Interface", + "id": "def-common.CheckPipelineRequestBody", + "type": "Type", "tags": [], - "label": "ESProcessorOptions", + "label": "CheckPipelineRequestBody", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions.on_failure", - "type": "Array", - "tags": [], - "label": "on_failure", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.ESProcessorItem", - "text": "ESProcessorItem" - }, - "[] | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions.ignore_failure", - "type": "CompoundType", - "tags": [], - "label": "ignore_failure", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions.ignore_missing", - "type": "CompoundType", - "tags": [], - "label": "ignore_missing", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions.if", - "type": "string", - "tags": [], - "label": "if", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions.tag", - "type": "string", - "tags": [], - "label": "tag", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.ESProcessorOptions.Unnamed", - "type": "IndexSignature", - "tags": [], - "label": "[key: string]: unknown", - "description": [], - "signature": [ - "[key: string]: unknown" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "signature": [ + "{ rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }" ], + "path": "x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.Integration", - "type": "Interface", + "id": "def-common.CheckPipelineResponse", + "type": "Type", "tags": [], - "label": "Integration", + "label": "CheckPipelineResponse", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Integration.name", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Integration.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Integration.description", - "type": "string", - "tags": [], - "label": "description", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Integration.dataStreams", - "type": "Array", - "tags": [], - "label": "dataStreams", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.DataStream", - "text": "DataStream" - }, - "[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Integration.logo", - "type": "string", - "tags": [], - "label": "logo", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "signature": [ + "{ pipelineResults: {}[]; errors?: {}[] | undefined; }" ], + "path": "x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.Pipeline", - "type": "Interface", + "id": "def-common.Datastream", + "type": "Type", "tags": [], - "label": "Pipeline", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Pipeline.name", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Pipeline.description", - "type": "string", - "tags": [], - "label": "description", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Pipeline.version", - "type": "number", - "tags": [], - "label": "version", - "description": [], - "signature": [ - "number | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Pipeline.processors", - "type": "Array", - "tags": [], - "label": "processors", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.ESProcessorItem", - "text": "ESProcessorItem" - }, - "[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.Pipeline.on_failure", - "type": "Array", - "tags": [], - "label": "on_failure", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.ESProcessorItem", - "text": "ESProcessorItem" - }, - "[] | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiRequest", - "type": "Interface", - "tags": [], - "label": "RelatedApiRequest", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiRequest.packageName", - "type": "string", - "tags": [], - "label": "packageName", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, + "label": "Datastream", + "description": [ + "\nThe datastream object." + ], + "signature": [ + "{ name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiRequest.dataStreamName", - "type": "string", - "tags": [], - "label": "dataStreamName", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", { - "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiRequest.rawSamples", - "type": "Array", - "tags": [], - "label": "rawSamples", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiRequest.currentPipeline", - "type": "Uncategorized", - "tags": [], - "label": "currentPipeline", - "description": [], - "signature": [ - "object" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "[] | undefined; }; docs: {}[]; }" ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiResponse", - "type": "Interface", + "id": "def-common.ECS_GRAPH_PATH", + "type": "string", "tags": [], - "label": "RelatedApiResponse", + "label": "ECS_GRAPH_PATH", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", + "path": "x-pack/plugins/integration_assistant/common/constants.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.RelatedApiResponse.results", - "type": "Object", - "tags": [], - "label": "results", - "description": [], - "signature": [ - "{ pipeline: object; docs: object[]; }" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.TestPipelineApiRequest", - "type": "Interface", + "id": "def-common.EcsMappingRequestBody", + "type": "Type", "tags": [], - "label": "TestPipelineApiRequest", + "label": "EcsMappingRequestBody", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", + "signature": [ + "{ connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; mapping?: {} | undefined; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.TestPipelineApiRequest.rawSamples", - "type": "Array", - "tags": [], - "label": "rawSamples", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.TestPipelineApiRequest.currentPipeline", - "type": "Object", - "tags": [], - "label": "currentPipeline", - "description": [], - "signature": [ - { - "pluginId": "integrationAssistant", - "scope": "common", - "docId": "kibIntegrationAssistantPluginApi", - "section": "def-common.Pipeline", - "text": "Pipeline" - } - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.TestPipelineApiResponse", - "type": "Interface", + "id": "def-common.EcsMappingResponse", + "type": "Type", "tags": [], - "label": "TestPipelineApiResponse", + "label": "EcsMappingResponse", "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "integrationAssistant", - "id": "def-common.TestPipelineApiResponse.pipelineResults", - "type": "Array", - "tags": [], - "label": "pipelineResults", - "description": [], - "signature": [ - "object[]" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "integrationAssistant", - "id": "def-common.TestPipelineApiResponse.errors", - "type": "Array", - "tags": [], - "label": "errors", - "description": [], - "signature": [ - "object[] | undefined" - ], - "path": "x-pack/plugins/integration_assistant/common/types.ts", - "deprecated": false, - "trackAdoption": false - } + "signature": [ + "{ results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; mapping: {}; }; }" ], + "path": "x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false - } - ], - "enums": [ + }, { "parentPluginId": "integrationAssistant", - "id": "def-common.InputTypes", - "type": "Enum", + "id": "def-common.ESProcessorItem", + "type": "Type", "tags": [], - "label": "InputTypes", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/types.ts", + "label": "ESProcessorItem", + "description": [ + "\nProcessor item for the Elasticsearch processor." + ], + "signature": [ + "{ [x: string]: ", + "ESProcessorOptions", + "; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/processor_attributes.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false - } - ], - "misc": [ + }, { "parentPluginId": "integrationAssistant", - "id": "def-common.CATEGORIZATION_GRAPH_PATH", - "type": "string", + "id": "def-common.InputType", + "type": "Type", "tags": [], - "label": "CATEGORIZATION_GRAPH_PATH", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/constants.ts", + "label": "InputType", + "description": [ + "\nThe input type for the datastream to pull logs from." + ], + "signature": [ + "\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\"" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "integrationAssistant", - "id": "def-common.ECS_GRAPH_PATH", - "type": "string", + "id": "def-common.Integration", + "type": "Type", "tags": [], - "label": "ECS_GRAPH_PATH", - "description": [], - "path": "x-pack/plugins/integration_assistant/common/constants.ts", + "label": "Integration", + "description": [ + "\nThe integration object." + ], + "signature": [ + "{ name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -960,6 +403,39 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.Pipeline", + "type": "Type", + "tags": [], + "label": "Pipeline", + "description": [ + "\nThe pipeline object." + ], + "signature": [ + "{ processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "integrationAssistant", "id": "def-common.PLUGIN_ID", @@ -987,6 +463,68 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.RelatedRequestBody", + "type": "Type", + "tags": [], + "label": "RelatedRequestBody", + "description": [], + "signature": [ + "{ connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; currentPipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/related/related_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.RelatedResponse", + "type": "Type", + "tags": [], + "label": "RelatedResponse", + "description": [], + "signature": [ + "{ results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/related/related_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "integrationAssistant", "id": "def-common.TEST_PIPELINE_PATH", @@ -1000,6 +538,1353 @@ "initialIsOpen": false } ], - "objects": [] + "objects": [ + { + "parentPluginId": "integrationAssistant", + "id": "def-common.BuildIntegrationRequestBody", + "type": "Object", + "tags": [], + "label": "BuildIntegrationRequestBody", + "description": [], + "signature": [ + "Zod.ZodObject<{ integration: Zod.ZodObject<{ name: Zod.ZodString; title: Zod.ZodString; description: Zod.ZodString; dataStreams: Zod.ZodArray, \"many\">; rawSamples: Zod.ZodArray; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; docs: Zod.ZodArray, \"many\">; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }>, \"many\">; logo: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }; }, { integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.CategorizationRequestBody", + "type": "Object", + "tags": [], + "label": "CategorizationRequestBody", + "description": [], + "signature": [ + "Zod.ZodObject<{ packageName: Zod.ZodString; datastreamName: Zod.ZodString; rawSamples: Zod.ZodArray; currentPipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; connectorId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; currentPipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }, { connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; currentPipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.CategorizationResponse", + "type": "Object", + "tags": [], + "label": "CategorizationResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ results: Zod.ZodObject<{ docs: Zod.ZodArray, \"many\">; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }, { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }>; }, \"strip\", Zod.ZodTypeAny, { results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }; }, { results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.CheckPipelineRequestBody", + "type": "Object", + "tags": [], + "label": "CheckPipelineRequestBody", + "description": [], + "signature": [ + "Zod.ZodObject<{ rawSamples: Zod.ZodArray; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }, { rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.CheckPipelineResponse", + "type": "Object", + "tags": [], + "label": "CheckPipelineResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ pipelineResults: Zod.ZodArray, \"many\">; errors: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { pipelineResults: {}[]; errors?: {}[] | undefined; }, { pipelineResults: {}[]; errors?: {}[] | undefined; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/check_pipeline/check_pipeline.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.Datastream", + "type": "Object", + "tags": [], + "label": "Datastream", + "description": [], + "signature": [ + "Zod.ZodObject<{ name: Zod.ZodString; title: Zod.ZodString; description: Zod.ZodString; inputTypes: Zod.ZodArray, \"many\">; rawSamples: Zod.ZodArray; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; docs: Zod.ZodArray, \"many\">; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.EcsMappingRequestBody", + "type": "Object", + "tags": [], + "label": "EcsMappingRequestBody", + "description": [], + "signature": [ + "Zod.ZodObject<{ packageName: Zod.ZodString; datastreamName: Zod.ZodString; rawSamples: Zod.ZodArray; mapping: Zod.ZodOptional>; connectorId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; mapping?: {} | undefined; }, { connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; mapping?: {} | undefined; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.EcsMappingResponse", + "type": "Object", + "tags": [], + "label": "EcsMappingResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ results: Zod.ZodObject<{ mapping: Zod.ZodObject<{}, \"strip\", Zod.ZodTypeAny, {}, {}>; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; mapping: {}; }, { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; mapping: {}; }>; }, \"strip\", Zod.ZodTypeAny, { results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; mapping: {}; }; }, { results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; mapping: {}; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.ESProcessorItem", + "type": "Object", + "tags": [], + "label": "ESProcessorItem", + "description": [], + "signature": [ + "Zod.ZodType<", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + ", Zod.ZodTypeDef, ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + ">" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/processor_attributes.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.InputType", + "type": "Object", + "tags": [], + "label": "InputType", + "description": [], + "signature": [ + "Zod.ZodEnum<[\"aws_cloudwatch\", \"aws_s3\", \"azure_blob_storage\", \"azure_eventhub\", \"cloudfoundry\", \"filestream\", \"gcp_pubsub\", \"gcs\", \"http_endpoint\", \"journald\", \"kafka\", \"tcp\", \"udp\"]>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.Integration", + "type": "Object", + "tags": [], + "label": "Integration", + "description": [], + "signature": [ + "Zod.ZodObject<{ name: Zod.ZodString; title: Zod.ZodString; description: Zod.ZodString; dataStreams: Zod.ZodArray, \"many\">; rawSamples: Zod.ZodArray; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; docs: Zod.ZodArray, \"many\">; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }>, \"many\">; logo: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws_cloudwatch\" | \"aws_s3\" | \"azure_blob_storage\" | \"azure_eventhub\" | \"cloudfoundry\" | \"filestream\" | \"gcp_pubsub\" | \"gcs\" | \"http_endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }[]; logo?: string | undefined; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.Pipeline", + "type": "Object", + "tags": [], + "label": "Pipeline", + "description": [], + "signature": [ + "Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.RelatedRequestBody", + "type": "Object", + "tags": [], + "label": "RelatedRequestBody", + "description": [], + "signature": [ + "Zod.ZodObject<{ packageName: Zod.ZodString; datastreamName: Zod.ZodString; rawSamples: Zod.ZodArray; currentPipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; connectorId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; currentPipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }, { connectorId: string; packageName: string; rawSamples: string[]; datastreamName: string; currentPipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/related/related_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.RelatedResponse", + "type": "Object", + "tags": [], + "label": "RelatedResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ results: Zod.ZodObject<{ docs: Zod.ZodArray, \"many\">; pipeline: Zod.ZodObject<{ name: Zod.ZodOptional; description: Zod.ZodOptional; version: Zod.ZodOptional; processors: Zod.ZodArray, \"many\">; on_failure: Zod.ZodOptional, \"many\">>; }, \"strip\", Zod.ZodTypeAny, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }, { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }, { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }>; }, \"strip\", Zod.ZodTypeAny, { results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }; }, { results: { pipeline: { processors: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[]; name?: string | undefined; description?: string | undefined; version?: number | undefined; on_failure?: ", + { + "pluginId": "integrationAssistant", + "scope": "common", + "docId": "kibIntegrationAssistantPluginApi", + "section": "def-common.ESProcessorItem", + "text": "ESProcessorItem" + }, + "[] | undefined; }; docs: {}[]; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/related/related_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] } } \ No newline at end of file diff --git a/api_docs/integration_assistant.mdx b/api_docs/integration_assistant.mdx index 3843c88387c92..73b904ecb97c2 100644 --- a/api_docs/integration_assistant.mdx +++ b/api_docs/integration_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/integrationAssistant title: "integrationAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the integrationAssistant plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'integrationAssistant'] --- import integrationAssistantObj from './integration_assistant.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 69 | 0 | 69 | 0 | +| 38 | 0 | 33 | 1 | ## Server @@ -33,11 +33,8 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur ## Common -### Interfaces - - -### Enums - +### Objects + ### Consts, variables and types diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 357d85637bd47..871aeba226a58 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index 8de337c3c95d4..18caa601857ed 100644 --- a/api_docs/investigate.mdx +++ b/api_docs/investigate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigate title: "investigate" image: https://source.unsplash.com/400x175/?github description: API docs for the investigate plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index b06c821e80cda..767a83fd2f9b9 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index fa8abc5d1abe4..292449afdca28 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 01e342ac33cb7..b5f13d0ca6c0c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_pattern_analysis.mdx b/api_docs/kbn_aiops_log_pattern_analysis.mdx index ff4acdfbeb759..eb59d7fe3fd70 100644 --- a/api_docs/kbn_aiops_log_pattern_analysis.mdx +++ b/api_docs/kbn_aiops_log_pattern_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-pattern-analysis title: "@kbn/aiops-log-pattern-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-pattern-analysis plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-pattern-analysis'] --- import kbnAiopsLogPatternAnalysisObj from './kbn_aiops_log_pattern_analysis.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_rate_analysis.mdx b/api_docs/kbn_aiops_log_rate_analysis.mdx index ec680f789947b..e54e82a6351ae 100644 --- a/api_docs/kbn_aiops_log_rate_analysis.mdx +++ b/api_docs/kbn_aiops_log_rate_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-rate-analysis title: "@kbn/aiops-log-rate-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-rate-analysis plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-rate-analysis'] --- import kbnAiopsLogRateAnalysisObj from './kbn_aiops_log_rate_analysis.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index 227b93cbe6c80..e1ef20d3f3fc8 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_comparators.mdx b/api_docs/kbn_alerting_comparators.mdx index e8909afd96cd6..bc0c50bbd4d12 100644 --- a/api_docs/kbn_alerting_comparators.mdx +++ b/api_docs/kbn_alerting_comparators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-comparators title: "@kbn/alerting-comparators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-comparators plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-comparators'] --- import kbnAlertingComparatorsObj from './kbn_alerting_comparators.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 7162776bea72e..0a6362b629c29 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index df3d3c1ebde23..e2ea27e979346 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.devdocs.json b/api_docs/kbn_alerts_as_data_utils.devdocs.json index 01dc34570dabc..ddb8b8183ad05 100644 --- a/api_docs/kbn_alerts_as_data_utils.devdocs.json +++ b/api_docs/kbn_alerts_as_data_utils.devdocs.json @@ -450,7 +450,7 @@ "label": "StackAlert", "description": [], "signature": [ - "{} & { 'kibana.alert.evaluation.conditions'?: string | undefined; 'kibana.alert.evaluation.threshold'?: string | number | undefined; 'kibana.alert.evaluation.value'?: string | undefined; 'kibana.alert.title'?: string | undefined; } & { '@timestamp': string | number; 'kibana.alert.instance.id': string; 'kibana.alert.rule.category': string; 'kibana.alert.rule.consumer': string; 'kibana.alert.rule.name': string; 'kibana.alert.rule.producer': string; 'kibana.alert.rule.revision': string | number; 'kibana.alert.rule.rule_type_id': string; 'kibana.alert.rule.uuid': string; 'kibana.alert.status': string; 'kibana.alert.uuid': string; 'kibana.space_ids': string[]; } & { 'event.action'?: string | undefined; 'event.kind'?: string | undefined; 'kibana.alert.action_group'?: string | undefined; 'kibana.alert.case_ids'?: string[] | undefined; 'kibana.alert.consecutive_matches'?: string | number | undefined; 'kibana.alert.duration.us'?: string | number | undefined; 'kibana.alert.end'?: string | number | undefined; 'kibana.alert.flapping'?: boolean | undefined; 'kibana.alert.flapping_history'?: boolean[] | undefined; 'kibana.alert.last_detected'?: string | number | undefined; 'kibana.alert.maintenance_window_ids'?: string[] | undefined; 'kibana.alert.reason'?: string | undefined; 'kibana.alert.rule.execution.timestamp'?: string | number | undefined; 'kibana.alert.rule.execution.uuid'?: string | undefined; 'kibana.alert.rule.parameters'?: unknown; 'kibana.alert.rule.tags'?: string[] | undefined; 'kibana.alert.start'?: string | number | undefined; 'kibana.alert.time_range'?: { gte?: string | number | undefined; lte?: string | number | undefined; } | undefined; 'kibana.alert.url'?: string | undefined; 'kibana.alert.workflow_assignee_ids'?: string[] | undefined; 'kibana.alert.workflow_status'?: string | undefined; 'kibana.alert.workflow_tags'?: string[] | undefined; 'kibana.version'?: string | undefined; tags?: string[] | undefined; }" + "{} & { 'kibana.alert.evaluation.conditions'?: string | undefined; 'kibana.alert.evaluation.threshold'?: string | number | undefined; 'kibana.alert.evaluation.value'?: string | undefined; 'kibana.alert.title'?: string | undefined; } & { '@timestamp': string | number; 'kibana.alert.instance.id': string; 'kibana.alert.rule.category': string; 'kibana.alert.rule.consumer': string; 'kibana.alert.rule.name': string; 'kibana.alert.rule.producer': string; 'kibana.alert.rule.revision': string | number; 'kibana.alert.rule.rule_type_id': string; 'kibana.alert.rule.uuid': string; 'kibana.alert.status': string; 'kibana.alert.uuid': string; 'kibana.space_ids': string[]; } & { 'event.action'?: string | undefined; 'event.kind'?: string | undefined; 'kibana.alert.action_group'?: string | undefined; 'kibana.alert.case_ids'?: string[] | undefined; 'kibana.alert.consecutive_matches'?: string | number | undefined; 'kibana.alert.duration.us'?: string | number | undefined; 'kibana.alert.end'?: string | number | undefined; 'kibana.alert.flapping'?: boolean | undefined; 'kibana.alert.flapping_history'?: boolean[] | undefined; 'kibana.alert.last_detected'?: string | number | undefined; 'kibana.alert.maintenance_window_ids'?: string[] | undefined; 'kibana.alert.reason'?: string | undefined; 'kibana.alert.rule.execution.timestamp'?: string | number | undefined; 'kibana.alert.rule.execution.uuid'?: string | undefined; 'kibana.alert.rule.parameters'?: unknown; 'kibana.alert.rule.tags'?: string[] | undefined; 'kibana.alert.start'?: string | number | undefined; 'kibana.alert.time_range'?: { gte?: string | number | undefined; lte?: string | number | undefined; } | undefined; 'kibana.alert.url'?: string | undefined; 'kibana.alert.workflow_assignee_ids'?: string[] | undefined; 'kibana.alert.workflow_status'?: string | undefined; 'kibana.alert.workflow_tags'?: string[] | undefined; 'kibana.version'?: string | undefined; tags?: string[] | undefined; } & { '@timestamp': string | number; 'ecs.version': string; } & { 'agent.build.original'?: string | undefined; 'agent.ephemeral_id'?: string | undefined; 'agent.id'?: string | undefined; 'agent.name'?: string | undefined; 'agent.type'?: string | undefined; 'agent.version'?: string | undefined; 'client.address'?: string | undefined; 'client.as.number'?: string | number | undefined; 'client.as.organization.name'?: string | undefined; 'client.bytes'?: string | number | undefined; 'client.domain'?: string | undefined; 'client.geo.city_name'?: string | undefined; 'client.geo.continent_code'?: string | undefined; 'client.geo.continent_name'?: string | undefined; 'client.geo.country_iso_code'?: string | undefined; 'client.geo.country_name'?: string | undefined; 'client.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'client.geo.name'?: string | undefined; 'client.geo.postal_code'?: string | undefined; 'client.geo.region_iso_code'?: string | undefined; 'client.geo.region_name'?: string | undefined; 'client.geo.timezone'?: string | undefined; 'client.ip'?: string | undefined; 'client.mac'?: string | undefined; 'client.nat.ip'?: string | undefined; 'client.nat.port'?: string | number | undefined; 'client.packets'?: string | number | undefined; 'client.port'?: string | number | undefined; 'client.registered_domain'?: string | undefined; 'client.subdomain'?: string | undefined; 'client.top_level_domain'?: string | undefined; 'client.user.domain'?: string | undefined; 'client.user.email'?: string | undefined; 'client.user.full_name'?: string | undefined; 'client.user.group.domain'?: string | undefined; 'client.user.group.id'?: string | undefined; 'client.user.group.name'?: string | undefined; 'client.user.hash'?: string | undefined; 'client.user.id'?: string | undefined; 'client.user.name'?: string | undefined; 'client.user.roles'?: string[] | undefined; 'cloud.account.id'?: string | undefined; 'cloud.account.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.instance.id'?: string | undefined; 'cloud.instance.name'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.origin.account.id'?: string | undefined; 'cloud.origin.account.name'?: string | undefined; 'cloud.origin.availability_zone'?: string | undefined; 'cloud.origin.instance.id'?: string | undefined; 'cloud.origin.instance.name'?: string | undefined; 'cloud.origin.machine.type'?: string | undefined; 'cloud.origin.project.id'?: string | undefined; 'cloud.origin.project.name'?: string | undefined; 'cloud.origin.provider'?: string | undefined; 'cloud.origin.region'?: string | undefined; 'cloud.origin.service.name'?: string | undefined; 'cloud.project.id'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.provider'?: string | undefined; 'cloud.region'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.target.account.id'?: string | undefined; 'cloud.target.account.name'?: string | undefined; 'cloud.target.availability_zone'?: string | undefined; 'cloud.target.instance.id'?: string | undefined; 'cloud.target.instance.name'?: string | undefined; 'cloud.target.machine.type'?: string | undefined; 'cloud.target.project.id'?: string | undefined; 'cloud.target.project.name'?: string | undefined; 'cloud.target.provider'?: string | undefined; 'cloud.target.region'?: string | undefined; 'cloud.target.service.name'?: string | undefined; 'container.cpu.usage'?: string | number | undefined; 'container.disk.read.bytes'?: string | number | undefined; 'container.disk.write.bytes'?: string | number | undefined; 'container.id'?: string | undefined; 'container.image.hash.all'?: string[] | undefined; 'container.image.name'?: string | undefined; 'container.image.tag'?: string[] | undefined; 'container.labels'?: unknown; 'container.memory.usage'?: string | number | undefined; 'container.name'?: string | undefined; 'container.network.egress.bytes'?: string | number | undefined; 'container.network.ingress.bytes'?: string | number | undefined; 'container.runtime'?: string | undefined; 'container.security_context.privileged'?: boolean | undefined; 'destination.address'?: string | undefined; 'destination.as.number'?: string | number | undefined; 'destination.as.organization.name'?: string | undefined; 'destination.bytes'?: string | number | undefined; 'destination.domain'?: string | undefined; 'destination.geo.city_name'?: string | undefined; 'destination.geo.continent_code'?: string | undefined; 'destination.geo.continent_name'?: string | undefined; 'destination.geo.country_iso_code'?: string | undefined; 'destination.geo.country_name'?: string | undefined; 'destination.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'destination.geo.name'?: string | undefined; 'destination.geo.postal_code'?: string | undefined; 'destination.geo.region_iso_code'?: string | undefined; 'destination.geo.region_name'?: string | undefined; 'destination.geo.timezone'?: string | undefined; 'destination.ip'?: string | undefined; 'destination.mac'?: string | undefined; 'destination.nat.ip'?: string | undefined; 'destination.nat.port'?: string | number | undefined; 'destination.packets'?: string | number | undefined; 'destination.port'?: string | number | undefined; 'destination.registered_domain'?: string | undefined; 'destination.subdomain'?: string | undefined; 'destination.top_level_domain'?: string | undefined; 'destination.user.domain'?: string | undefined; 'destination.user.email'?: string | undefined; 'destination.user.full_name'?: string | undefined; 'destination.user.group.domain'?: string | undefined; 'destination.user.group.id'?: string | undefined; 'destination.user.group.name'?: string | undefined; 'destination.user.hash'?: string | undefined; 'destination.user.id'?: string | undefined; 'destination.user.name'?: string | undefined; 'destination.user.roles'?: string[] | undefined; 'device.id'?: string | undefined; 'device.manufacturer'?: string | undefined; 'device.model.identifier'?: string | undefined; 'device.model.name'?: string | undefined; 'dll.code_signature.digest_algorithm'?: string | undefined; 'dll.code_signature.exists'?: boolean | undefined; 'dll.code_signature.signing_id'?: string | undefined; 'dll.code_signature.status'?: string | undefined; 'dll.code_signature.subject_name'?: string | undefined; 'dll.code_signature.team_id'?: string | undefined; 'dll.code_signature.timestamp'?: string | number | undefined; 'dll.code_signature.trusted'?: boolean | undefined; 'dll.code_signature.valid'?: boolean | undefined; 'dll.hash.md5'?: string | undefined; 'dll.hash.sha1'?: string | undefined; 'dll.hash.sha256'?: string | undefined; 'dll.hash.sha384'?: string | undefined; 'dll.hash.sha512'?: string | undefined; 'dll.hash.ssdeep'?: string | undefined; 'dll.hash.tlsh'?: string | undefined; 'dll.name'?: string | undefined; 'dll.path'?: string | undefined; 'dll.pe.architecture'?: string | undefined; 'dll.pe.company'?: string | undefined; 'dll.pe.description'?: string | undefined; 'dll.pe.file_version'?: string | undefined; 'dll.pe.go_import_hash'?: string | undefined; 'dll.pe.go_imports'?: unknown; 'dll.pe.go_imports_names_entropy'?: string | number | undefined; 'dll.pe.go_imports_names_var_entropy'?: string | number | undefined; 'dll.pe.go_stripped'?: boolean | undefined; 'dll.pe.imphash'?: string | undefined; 'dll.pe.import_hash'?: string | undefined; 'dll.pe.imports'?: unknown[] | undefined; 'dll.pe.imports_names_entropy'?: string | number | undefined; 'dll.pe.imports_names_var_entropy'?: string | number | undefined; 'dll.pe.original_file_name'?: string | undefined; 'dll.pe.pehash'?: string | undefined; 'dll.pe.product'?: string | undefined; 'dll.pe.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'dns.answers'?: { class?: string | undefined; data?: string | undefined; name?: string | undefined; ttl?: string | number | undefined; type?: string | undefined; }[] | undefined; 'dns.header_flags'?: string[] | undefined; 'dns.id'?: string | undefined; 'dns.op_code'?: string | undefined; 'dns.question.class'?: string | undefined; 'dns.question.name'?: string | undefined; 'dns.question.registered_domain'?: string | undefined; 'dns.question.subdomain'?: string | undefined; 'dns.question.top_level_domain'?: string | undefined; 'dns.question.type'?: string | undefined; 'dns.resolved_ip'?: string[] | undefined; 'dns.response_code'?: string | undefined; 'dns.type'?: string | undefined; 'email.attachments'?: { 'file.extension'?: string | undefined; 'file.hash.md5'?: string | undefined; 'file.hash.sha1'?: string | undefined; 'file.hash.sha256'?: string | undefined; 'file.hash.sha384'?: string | undefined; 'file.hash.sha512'?: string | undefined; 'file.hash.ssdeep'?: string | undefined; 'file.hash.tlsh'?: string | undefined; 'file.mime_type'?: string | undefined; 'file.name'?: string | undefined; 'file.size'?: string | number | undefined; }[] | undefined; 'email.bcc.address'?: string[] | undefined; 'email.cc.address'?: string[] | undefined; 'email.content_type'?: string | undefined; 'email.delivery_timestamp'?: string | number | undefined; 'email.direction'?: string | undefined; 'email.from.address'?: string[] | undefined; 'email.local_id'?: string | undefined; 'email.message_id'?: string | undefined; 'email.origination_timestamp'?: string | number | undefined; 'email.reply_to.address'?: string[] | undefined; 'email.sender.address'?: string | undefined; 'email.subject'?: string | undefined; 'email.to.address'?: string[] | undefined; 'email.x_mailer'?: string | undefined; 'error.code'?: string | undefined; 'error.id'?: string | undefined; 'error.message'?: string | undefined; 'error.stack_trace'?: string | undefined; 'error.type'?: string | undefined; 'event.action'?: string | undefined; 'event.agent_id_status'?: string | undefined; 'event.category'?: string[] | undefined; 'event.code'?: string | undefined; 'event.created'?: string | number | undefined; 'event.dataset'?: string | undefined; 'event.duration'?: string | number | undefined; 'event.end'?: string | number | undefined; 'event.hash'?: string | undefined; 'event.id'?: string | undefined; 'event.ingested'?: string | number | undefined; 'event.kind'?: string | undefined; 'event.module'?: string | undefined; 'event.original'?: string | undefined; 'event.outcome'?: string | undefined; 'event.provider'?: string | undefined; 'event.reason'?: string | undefined; 'event.reference'?: string | undefined; 'event.risk_score'?: number | undefined; 'event.risk_score_norm'?: number | undefined; 'event.sequence'?: string | number | undefined; 'event.severity'?: string | number | undefined; 'event.start'?: string | number | undefined; 'event.timezone'?: string | undefined; 'event.type'?: string[] | undefined; 'event.url'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.version'?: string | undefined; 'file.accessed'?: string | number | undefined; 'file.attributes'?: string[] | undefined; 'file.code_signature.digest_algorithm'?: string | undefined; 'file.code_signature.exists'?: boolean | undefined; 'file.code_signature.signing_id'?: string | undefined; 'file.code_signature.status'?: string | undefined; 'file.code_signature.subject_name'?: string | undefined; 'file.code_signature.team_id'?: string | undefined; 'file.code_signature.timestamp'?: string | number | undefined; 'file.code_signature.trusted'?: boolean | undefined; 'file.code_signature.valid'?: boolean | undefined; 'file.created'?: string | number | undefined; 'file.ctime'?: string | number | undefined; 'file.device'?: string | undefined; 'file.directory'?: string | undefined; 'file.drive_letter'?: string | undefined; 'file.elf.architecture'?: string | undefined; 'file.elf.byte_order'?: string | undefined; 'file.elf.cpu_type'?: string | undefined; 'file.elf.creation_date'?: string | number | undefined; 'file.elf.exports'?: unknown[] | undefined; 'file.elf.go_import_hash'?: string | undefined; 'file.elf.go_imports'?: unknown; 'file.elf.go_imports_names_entropy'?: string | number | undefined; 'file.elf.go_imports_names_var_entropy'?: string | number | undefined; 'file.elf.go_stripped'?: boolean | undefined; 'file.elf.header.abi_version'?: string | undefined; 'file.elf.header.class'?: string | undefined; 'file.elf.header.data'?: string | undefined; 'file.elf.header.entrypoint'?: string | number | undefined; 'file.elf.header.object_version'?: string | undefined; 'file.elf.header.os_abi'?: string | undefined; 'file.elf.header.type'?: string | undefined; 'file.elf.header.version'?: string | undefined; 'file.elf.import_hash'?: string | undefined; 'file.elf.imports'?: unknown[] | undefined; 'file.elf.imports_names_entropy'?: string | number | undefined; 'file.elf.imports_names_var_entropy'?: string | number | undefined; 'file.elf.sections'?: { chi2?: string | number | undefined; entropy?: string | number | undefined; flags?: string | undefined; name?: string | undefined; physical_offset?: string | undefined; physical_size?: string | number | undefined; type?: string | undefined; var_entropy?: string | number | undefined; virtual_address?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'file.elf.segments'?: { sections?: string | undefined; type?: string | undefined; }[] | undefined; 'file.elf.shared_libraries'?: string[] | undefined; 'file.elf.telfhash'?: string | undefined; 'file.extension'?: string | undefined; 'file.fork_name'?: string | undefined; 'file.gid'?: string | undefined; 'file.group'?: string | undefined; 'file.hash.md5'?: string | undefined; 'file.hash.sha1'?: string | undefined; 'file.hash.sha256'?: string | undefined; 'file.hash.sha384'?: string | undefined; 'file.hash.sha512'?: string | undefined; 'file.hash.ssdeep'?: string | undefined; 'file.hash.tlsh'?: string | undefined; 'file.inode'?: string | undefined; 'file.macho.go_import_hash'?: string | undefined; 'file.macho.go_imports'?: unknown; 'file.macho.go_imports_names_entropy'?: string | number | undefined; 'file.macho.go_imports_names_var_entropy'?: string | number | undefined; 'file.macho.go_stripped'?: boolean | undefined; 'file.macho.import_hash'?: string | undefined; 'file.macho.imports'?: unknown[] | undefined; 'file.macho.imports_names_entropy'?: string | number | undefined; 'file.macho.imports_names_var_entropy'?: string | number | undefined; 'file.macho.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'file.macho.symhash'?: string | undefined; 'file.mime_type'?: string | undefined; 'file.mode'?: string | undefined; 'file.mtime'?: string | number | undefined; 'file.name'?: string | undefined; 'file.owner'?: string | undefined; 'file.path'?: string | undefined; 'file.pe.architecture'?: string | undefined; 'file.pe.company'?: string | undefined; 'file.pe.description'?: string | undefined; 'file.pe.file_version'?: string | undefined; 'file.pe.go_import_hash'?: string | undefined; 'file.pe.go_imports'?: unknown; 'file.pe.go_imports_names_entropy'?: string | number | undefined; 'file.pe.go_imports_names_var_entropy'?: string | number | undefined; 'file.pe.go_stripped'?: boolean | undefined; 'file.pe.imphash'?: string | undefined; 'file.pe.import_hash'?: string | undefined; 'file.pe.imports'?: unknown[] | undefined; 'file.pe.imports_names_entropy'?: string | number | undefined; 'file.pe.imports_names_var_entropy'?: string | number | undefined; 'file.pe.original_file_name'?: string | undefined; 'file.pe.pehash'?: string | undefined; 'file.pe.product'?: string | undefined; 'file.pe.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'file.size'?: string | number | undefined; 'file.target_path'?: string | undefined; 'file.type'?: string | undefined; 'file.uid'?: string | undefined; 'file.x509.alternative_names'?: string[] | undefined; 'file.x509.issuer.common_name'?: string[] | undefined; 'file.x509.issuer.country'?: string[] | undefined; 'file.x509.issuer.distinguished_name'?: string | undefined; 'file.x509.issuer.locality'?: string[] | undefined; 'file.x509.issuer.organization'?: string[] | undefined; 'file.x509.issuer.organizational_unit'?: string[] | undefined; 'file.x509.issuer.state_or_province'?: string[] | undefined; 'file.x509.not_after'?: string | number | undefined; 'file.x509.not_before'?: string | number | undefined; 'file.x509.public_key_algorithm'?: string | undefined; 'file.x509.public_key_curve'?: string | undefined; 'file.x509.public_key_exponent'?: string | number | undefined; 'file.x509.public_key_size'?: string | number | undefined; 'file.x509.serial_number'?: string | undefined; 'file.x509.signature_algorithm'?: string | undefined; 'file.x509.subject.common_name'?: string[] | undefined; 'file.x509.subject.country'?: string[] | undefined; 'file.x509.subject.distinguished_name'?: string | undefined; 'file.x509.subject.locality'?: string[] | undefined; 'file.x509.subject.organization'?: string[] | undefined; 'file.x509.subject.organizational_unit'?: string[] | undefined; 'file.x509.subject.state_or_province'?: string[] | undefined; 'file.x509.version_number'?: string | undefined; 'group.domain'?: string | undefined; 'group.id'?: string | undefined; 'group.name'?: string | undefined; 'host.architecture'?: string | undefined; 'host.boot.id'?: string | undefined; 'host.cpu.usage'?: string | number | undefined; 'host.disk.read.bytes'?: string | number | undefined; 'host.disk.write.bytes'?: string | number | undefined; 'host.domain'?: string | undefined; 'host.geo.city_name'?: string | undefined; 'host.geo.continent_code'?: string | undefined; 'host.geo.continent_name'?: string | undefined; 'host.geo.country_iso_code'?: string | undefined; 'host.geo.country_name'?: string | undefined; 'host.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'host.geo.name'?: string | undefined; 'host.geo.postal_code'?: string | undefined; 'host.geo.region_iso_code'?: string | undefined; 'host.geo.region_name'?: string | undefined; 'host.geo.timezone'?: string | undefined; 'host.hostname'?: string | undefined; 'host.id'?: string | undefined; 'host.ip'?: string[] | undefined; 'host.mac'?: string[] | undefined; 'host.name'?: string | undefined; 'host.network.egress.bytes'?: string | number | undefined; 'host.network.egress.packets'?: string | number | undefined; 'host.network.ingress.bytes'?: string | number | undefined; 'host.network.ingress.packets'?: string | number | undefined; 'host.os.family'?: string | undefined; 'host.os.full'?: string | undefined; 'host.os.kernel'?: string | undefined; 'host.os.name'?: string | undefined; 'host.os.platform'?: string | undefined; 'host.os.type'?: string | undefined; 'host.os.version'?: string | undefined; 'host.pid_ns_ino'?: string | undefined; 'host.risk.calculated_level'?: string | undefined; 'host.risk.calculated_score'?: number | undefined; 'host.risk.calculated_score_norm'?: number | undefined; 'host.risk.static_level'?: string | undefined; 'host.risk.static_score'?: number | undefined; 'host.risk.static_score_norm'?: number | undefined; 'host.type'?: string | undefined; 'host.uptime'?: string | number | undefined; 'http.request.body.bytes'?: string | number | undefined; 'http.request.body.content'?: string | undefined; 'http.request.bytes'?: string | number | undefined; 'http.request.id'?: string | undefined; 'http.request.method'?: string | undefined; 'http.request.mime_type'?: string | undefined; 'http.request.referrer'?: string | undefined; 'http.response.body.bytes'?: string | number | undefined; 'http.response.body.content'?: string | undefined; 'http.response.bytes'?: string | number | undefined; 'http.response.mime_type'?: string | undefined; 'http.response.status_code'?: string | number | undefined; 'http.version'?: string | undefined; labels?: unknown; 'log.file.path'?: string | undefined; 'log.level'?: string | undefined; 'log.logger'?: string | undefined; 'log.origin.file.line'?: string | number | undefined; 'log.origin.file.name'?: string | undefined; 'log.origin.function'?: string | undefined; 'log.syslog'?: unknown; message?: string | undefined; 'network.application'?: string | undefined; 'network.bytes'?: string | number | undefined; 'network.community_id'?: string | undefined; 'network.direction'?: string | undefined; 'network.forwarded_ip'?: string | undefined; 'network.iana_number'?: string | undefined; 'network.inner'?: unknown; 'network.name'?: string | undefined; 'network.packets'?: string | number | undefined; 'network.protocol'?: string | undefined; 'network.transport'?: string | undefined; 'network.type'?: string | undefined; 'network.vlan.id'?: string | undefined; 'network.vlan.name'?: string | undefined; 'observer.egress'?: unknown; 'observer.geo.city_name'?: string | undefined; 'observer.geo.continent_code'?: string | undefined; 'observer.geo.continent_name'?: string | undefined; 'observer.geo.country_iso_code'?: string | undefined; 'observer.geo.country_name'?: string | undefined; 'observer.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'observer.geo.name'?: string | undefined; 'observer.geo.postal_code'?: string | undefined; 'observer.geo.region_iso_code'?: string | undefined; 'observer.geo.region_name'?: string | undefined; 'observer.geo.timezone'?: string | undefined; 'observer.hostname'?: string | undefined; 'observer.ingress'?: unknown; 'observer.ip'?: string[] | undefined; 'observer.mac'?: string[] | undefined; 'observer.name'?: string | undefined; 'observer.os.family'?: string | undefined; 'observer.os.full'?: string | undefined; 'observer.os.kernel'?: string | undefined; 'observer.os.name'?: string | undefined; 'observer.os.platform'?: string | undefined; 'observer.os.type'?: string | undefined; 'observer.os.version'?: string | undefined; 'observer.product'?: string | undefined; 'observer.serial_number'?: string | undefined; 'observer.type'?: string | undefined; 'observer.vendor'?: string | undefined; 'observer.version'?: string | undefined; 'orchestrator.api_version'?: string | undefined; 'orchestrator.cluster.id'?: string | undefined; 'orchestrator.cluster.name'?: string | undefined; 'orchestrator.cluster.url'?: string | undefined; 'orchestrator.cluster.version'?: string | undefined; 'orchestrator.namespace'?: string | undefined; 'orchestrator.organization'?: string | undefined; 'orchestrator.resource.annotation'?: string[] | undefined; 'orchestrator.resource.id'?: string | undefined; 'orchestrator.resource.ip'?: string[] | undefined; 'orchestrator.resource.label'?: string[] | undefined; 'orchestrator.resource.name'?: string | undefined; 'orchestrator.resource.parent.type'?: string | undefined; 'orchestrator.resource.type'?: string | undefined; 'orchestrator.type'?: string | undefined; 'organization.id'?: string | undefined; 'organization.name'?: string | undefined; 'package.architecture'?: string | undefined; 'package.build_version'?: string | undefined; 'package.checksum'?: string | undefined; 'package.description'?: string | undefined; 'package.install_scope'?: string | undefined; 'package.installed'?: string | number | undefined; 'package.license'?: string | undefined; 'package.name'?: string | undefined; 'package.path'?: string | undefined; 'package.reference'?: string | undefined; 'package.size'?: string | number | undefined; 'package.type'?: string | undefined; 'package.version'?: string | undefined; 'process.args'?: string[] | undefined; 'process.args_count'?: string | number | undefined; 'process.code_signature.digest_algorithm'?: string | undefined; 'process.code_signature.exists'?: boolean | undefined; 'process.code_signature.signing_id'?: string | undefined; 'process.code_signature.status'?: string | undefined; 'process.code_signature.subject_name'?: string | undefined; 'process.code_signature.team_id'?: string | undefined; 'process.code_signature.timestamp'?: string | number | undefined; 'process.code_signature.trusted'?: boolean | undefined; 'process.code_signature.valid'?: boolean | undefined; 'process.command_line'?: string | undefined; 'process.elf.architecture'?: string | undefined; 'process.elf.byte_order'?: string | undefined; 'process.elf.cpu_type'?: string | undefined; 'process.elf.creation_date'?: string | number | undefined; 'process.elf.exports'?: unknown[] | undefined; 'process.elf.go_import_hash'?: string | undefined; 'process.elf.go_imports'?: unknown; 'process.elf.go_imports_names_entropy'?: string | number | undefined; 'process.elf.go_imports_names_var_entropy'?: string | number | undefined; 'process.elf.go_stripped'?: boolean | undefined; 'process.elf.header.abi_version'?: string | undefined; 'process.elf.header.class'?: string | undefined; 'process.elf.header.data'?: string | undefined; 'process.elf.header.entrypoint'?: string | number | undefined; 'process.elf.header.object_version'?: string | undefined; 'process.elf.header.os_abi'?: string | undefined; 'process.elf.header.type'?: string | undefined; 'process.elf.header.version'?: string | undefined; 'process.elf.import_hash'?: string | undefined; 'process.elf.imports'?: unknown[] | undefined; 'process.elf.imports_names_entropy'?: string | number | undefined; 'process.elf.imports_names_var_entropy'?: string | number | undefined; 'process.elf.sections'?: { chi2?: string | number | undefined; entropy?: string | number | undefined; flags?: string | undefined; name?: string | undefined; physical_offset?: string | undefined; physical_size?: string | number | undefined; type?: string | undefined; var_entropy?: string | number | undefined; virtual_address?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'process.elf.segments'?: { sections?: string | undefined; type?: string | undefined; }[] | undefined; 'process.elf.shared_libraries'?: string[] | undefined; 'process.elf.telfhash'?: string | undefined; 'process.end'?: string | number | undefined; 'process.entity_id'?: string | undefined; 'process.entry_leader.args'?: string[] | undefined; 'process.entry_leader.args_count'?: string | number | undefined; 'process.entry_leader.attested_groups.name'?: string | undefined; 'process.entry_leader.attested_user.id'?: string | undefined; 'process.entry_leader.attested_user.name'?: string | undefined; 'process.entry_leader.command_line'?: string | undefined; 'process.entry_leader.entity_id'?: string | undefined; 'process.entry_leader.entry_meta.source.ip'?: string | undefined; 'process.entry_leader.entry_meta.type'?: string | undefined; 'process.entry_leader.executable'?: string | undefined; 'process.entry_leader.group.id'?: string | undefined; 'process.entry_leader.group.name'?: string | undefined; 'process.entry_leader.interactive'?: boolean | undefined; 'process.entry_leader.name'?: string | undefined; 'process.entry_leader.parent.entity_id'?: string | undefined; 'process.entry_leader.parent.pid'?: string | number | undefined; 'process.entry_leader.parent.session_leader.entity_id'?: string | undefined; 'process.entry_leader.parent.session_leader.pid'?: string | number | undefined; 'process.entry_leader.parent.session_leader.start'?: string | number | undefined; 'process.entry_leader.parent.session_leader.vpid'?: string | number | undefined; 'process.entry_leader.parent.start'?: string | number | undefined; 'process.entry_leader.parent.vpid'?: string | number | undefined; 'process.entry_leader.pid'?: string | number | undefined; 'process.entry_leader.real_group.id'?: string | undefined; 'process.entry_leader.real_group.name'?: string | undefined; 'process.entry_leader.real_user.id'?: string | undefined; 'process.entry_leader.real_user.name'?: string | undefined; 'process.entry_leader.same_as_process'?: boolean | undefined; 'process.entry_leader.saved_group.id'?: string | undefined; 'process.entry_leader.saved_group.name'?: string | undefined; 'process.entry_leader.saved_user.id'?: string | undefined; 'process.entry_leader.saved_user.name'?: string | undefined; 'process.entry_leader.start'?: string | number | undefined; 'process.entry_leader.supplemental_groups.id'?: string | undefined; 'process.entry_leader.supplemental_groups.name'?: string | undefined; 'process.entry_leader.tty'?: unknown; 'process.entry_leader.user.id'?: string | undefined; 'process.entry_leader.user.name'?: string | undefined; 'process.entry_leader.vpid'?: string | number | undefined; 'process.entry_leader.working_directory'?: string | undefined; 'process.env_vars'?: string[] | undefined; 'process.executable'?: string | undefined; 'process.exit_code'?: string | number | undefined; 'process.group_leader.args'?: string[] | undefined; 'process.group_leader.args_count'?: string | number | undefined; 'process.group_leader.command_line'?: string | undefined; 'process.group_leader.entity_id'?: string | undefined; 'process.group_leader.executable'?: string | undefined; 'process.group_leader.group.id'?: string | undefined; 'process.group_leader.group.name'?: string | undefined; 'process.group_leader.interactive'?: boolean | undefined; 'process.group_leader.name'?: string | undefined; 'process.group_leader.pid'?: string | number | undefined; 'process.group_leader.real_group.id'?: string | undefined; 'process.group_leader.real_group.name'?: string | undefined; 'process.group_leader.real_user.id'?: string | undefined; 'process.group_leader.real_user.name'?: string | undefined; 'process.group_leader.same_as_process'?: boolean | undefined; 'process.group_leader.saved_group.id'?: string | undefined; 'process.group_leader.saved_group.name'?: string | undefined; 'process.group_leader.saved_user.id'?: string | undefined; 'process.group_leader.saved_user.name'?: string | undefined; 'process.group_leader.start'?: string | number | undefined; 'process.group_leader.supplemental_groups.id'?: string | undefined; 'process.group_leader.supplemental_groups.name'?: string | undefined; 'process.group_leader.tty'?: unknown; 'process.group_leader.user.id'?: string | undefined; 'process.group_leader.user.name'?: string | undefined; 'process.group_leader.vpid'?: string | number | undefined; 'process.group_leader.working_directory'?: string | undefined; 'process.hash.md5'?: string | undefined; 'process.hash.sha1'?: string | undefined; 'process.hash.sha256'?: string | undefined; 'process.hash.sha384'?: string | undefined; 'process.hash.sha512'?: string | undefined; 'process.hash.ssdeep'?: string | undefined; 'process.hash.tlsh'?: string | undefined; 'process.interactive'?: boolean | undefined; 'process.io'?: unknown; 'process.macho.go_import_hash'?: string | undefined; 'process.macho.go_imports'?: unknown; 'process.macho.go_imports_names_entropy'?: string | number | undefined; 'process.macho.go_imports_names_var_entropy'?: string | number | undefined; 'process.macho.go_stripped'?: boolean | undefined; 'process.macho.import_hash'?: string | undefined; 'process.macho.imports'?: unknown[] | undefined; 'process.macho.imports_names_entropy'?: string | number | undefined; 'process.macho.imports_names_var_entropy'?: string | number | undefined; 'process.macho.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'process.macho.symhash'?: string | undefined; 'process.name'?: string | undefined; 'process.parent.args'?: string[] | undefined; 'process.parent.args_count'?: string | number | undefined; 'process.parent.code_signature.digest_algorithm'?: string | undefined; 'process.parent.code_signature.exists'?: boolean | undefined; 'process.parent.code_signature.signing_id'?: string | undefined; 'process.parent.code_signature.status'?: string | undefined; 'process.parent.code_signature.subject_name'?: string | undefined; 'process.parent.code_signature.team_id'?: string | undefined; 'process.parent.code_signature.timestamp'?: string | number | undefined; 'process.parent.code_signature.trusted'?: boolean | undefined; 'process.parent.code_signature.valid'?: boolean | undefined; 'process.parent.command_line'?: string | undefined; 'process.parent.elf.architecture'?: string | undefined; 'process.parent.elf.byte_order'?: string | undefined; 'process.parent.elf.cpu_type'?: string | undefined; 'process.parent.elf.creation_date'?: string | number | undefined; 'process.parent.elf.exports'?: unknown[] | undefined; 'process.parent.elf.go_import_hash'?: string | undefined; 'process.parent.elf.go_imports'?: unknown; 'process.parent.elf.go_imports_names_entropy'?: string | number | undefined; 'process.parent.elf.go_imports_names_var_entropy'?: string | number | undefined; 'process.parent.elf.go_stripped'?: boolean | undefined; 'process.parent.elf.header.abi_version'?: string | undefined; 'process.parent.elf.header.class'?: string | undefined; 'process.parent.elf.header.data'?: string | undefined; 'process.parent.elf.header.entrypoint'?: string | number | undefined; 'process.parent.elf.header.object_version'?: string | undefined; 'process.parent.elf.header.os_abi'?: string | undefined; 'process.parent.elf.header.type'?: string | undefined; 'process.parent.elf.header.version'?: string | undefined; 'process.parent.elf.import_hash'?: string | undefined; 'process.parent.elf.imports'?: unknown[] | undefined; 'process.parent.elf.imports_names_entropy'?: string | number | undefined; 'process.parent.elf.imports_names_var_entropy'?: string | number | undefined; 'process.parent.elf.sections'?: { chi2?: string | number | undefined; entropy?: string | number | undefined; flags?: string | undefined; name?: string | undefined; physical_offset?: string | undefined; physical_size?: string | number | undefined; type?: string | undefined; var_entropy?: string | number | undefined; virtual_address?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'process.parent.elf.segments'?: { sections?: string | undefined; type?: string | undefined; }[] | undefined; 'process.parent.elf.shared_libraries'?: string[] | undefined; 'process.parent.elf.telfhash'?: string | undefined; 'process.parent.end'?: string | number | undefined; 'process.parent.entity_id'?: string | undefined; 'process.parent.executable'?: string | undefined; 'process.parent.exit_code'?: string | number | undefined; 'process.parent.group.id'?: string | undefined; 'process.parent.group.name'?: string | undefined; 'process.parent.group_leader.entity_id'?: string | undefined; 'process.parent.group_leader.pid'?: string | number | undefined; 'process.parent.group_leader.start'?: string | number | undefined; 'process.parent.group_leader.vpid'?: string | number | undefined; 'process.parent.hash.md5'?: string | undefined; 'process.parent.hash.sha1'?: string | undefined; 'process.parent.hash.sha256'?: string | undefined; 'process.parent.hash.sha384'?: string | undefined; 'process.parent.hash.sha512'?: string | undefined; 'process.parent.hash.ssdeep'?: string | undefined; 'process.parent.hash.tlsh'?: string | undefined; 'process.parent.interactive'?: boolean | undefined; 'process.parent.macho.go_import_hash'?: string | undefined; 'process.parent.macho.go_imports'?: unknown; 'process.parent.macho.go_imports_names_entropy'?: string | number | undefined; 'process.parent.macho.go_imports_names_var_entropy'?: string | number | undefined; 'process.parent.macho.go_stripped'?: boolean | undefined; 'process.parent.macho.import_hash'?: string | undefined; 'process.parent.macho.imports'?: unknown[] | undefined; 'process.parent.macho.imports_names_entropy'?: string | number | undefined; 'process.parent.macho.imports_names_var_entropy'?: string | number | undefined; 'process.parent.macho.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'process.parent.macho.symhash'?: string | undefined; 'process.parent.name'?: string | undefined; 'process.parent.pe.architecture'?: string | undefined; 'process.parent.pe.company'?: string | undefined; 'process.parent.pe.description'?: string | undefined; 'process.parent.pe.file_version'?: string | undefined; 'process.parent.pe.go_import_hash'?: string | undefined; 'process.parent.pe.go_imports'?: unknown; 'process.parent.pe.go_imports_names_entropy'?: string | number | undefined; 'process.parent.pe.go_imports_names_var_entropy'?: string | number | undefined; 'process.parent.pe.go_stripped'?: boolean | undefined; 'process.parent.pe.imphash'?: string | undefined; 'process.parent.pe.import_hash'?: string | undefined; 'process.parent.pe.imports'?: unknown[] | undefined; 'process.parent.pe.imports_names_entropy'?: string | number | undefined; 'process.parent.pe.imports_names_var_entropy'?: string | number | undefined; 'process.parent.pe.original_file_name'?: string | undefined; 'process.parent.pe.pehash'?: string | undefined; 'process.parent.pe.product'?: string | undefined; 'process.parent.pe.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'process.parent.pgid'?: string | number | undefined; 'process.parent.pid'?: string | number | undefined; 'process.parent.real_group.id'?: string | undefined; 'process.parent.real_group.name'?: string | undefined; 'process.parent.real_user.id'?: string | undefined; 'process.parent.real_user.name'?: string | undefined; 'process.parent.saved_group.id'?: string | undefined; 'process.parent.saved_group.name'?: string | undefined; 'process.parent.saved_user.id'?: string | undefined; 'process.parent.saved_user.name'?: string | undefined; 'process.parent.start'?: string | number | undefined; 'process.parent.supplemental_groups.id'?: string | undefined; 'process.parent.supplemental_groups.name'?: string | undefined; 'process.parent.thread.capabilities.effective'?: string[] | undefined; 'process.parent.thread.capabilities.permitted'?: string[] | undefined; 'process.parent.thread.id'?: string | number | undefined; 'process.parent.thread.name'?: string | undefined; 'process.parent.title'?: string | undefined; 'process.parent.tty'?: unknown; 'process.parent.uptime'?: string | number | undefined; 'process.parent.user.id'?: string | undefined; 'process.parent.user.name'?: string | undefined; 'process.parent.vpid'?: string | number | undefined; 'process.parent.working_directory'?: string | undefined; 'process.pe.architecture'?: string | undefined; 'process.pe.company'?: string | undefined; 'process.pe.description'?: string | undefined; 'process.pe.file_version'?: string | undefined; 'process.pe.go_import_hash'?: string | undefined; 'process.pe.go_imports'?: unknown; 'process.pe.go_imports_names_entropy'?: string | number | undefined; 'process.pe.go_imports_names_var_entropy'?: string | number | undefined; 'process.pe.go_stripped'?: boolean | undefined; 'process.pe.imphash'?: string | undefined; 'process.pe.import_hash'?: string | undefined; 'process.pe.imports'?: unknown[] | undefined; 'process.pe.imports_names_entropy'?: string | number | undefined; 'process.pe.imports_names_var_entropy'?: string | number | undefined; 'process.pe.original_file_name'?: string | undefined; 'process.pe.pehash'?: string | undefined; 'process.pe.product'?: string | undefined; 'process.pe.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'process.pgid'?: string | number | undefined; 'process.pid'?: string | number | undefined; 'process.previous.args'?: string[] | undefined; 'process.previous.args_count'?: string | number | undefined; 'process.previous.executable'?: string | undefined; 'process.real_group.id'?: string | undefined; 'process.real_group.name'?: string | undefined; 'process.real_user.id'?: string | undefined; 'process.real_user.name'?: string | undefined; 'process.saved_group.id'?: string | undefined; 'process.saved_group.name'?: string | undefined; 'process.saved_user.id'?: string | undefined; 'process.saved_user.name'?: string | undefined; 'process.session_leader.args'?: string[] | undefined; 'process.session_leader.args_count'?: string | number | undefined; 'process.session_leader.command_line'?: string | undefined; 'process.session_leader.entity_id'?: string | undefined; 'process.session_leader.executable'?: string | undefined; 'process.session_leader.group.id'?: string | undefined; 'process.session_leader.group.name'?: string | undefined; 'process.session_leader.interactive'?: boolean | undefined; 'process.session_leader.name'?: string | undefined; 'process.session_leader.parent.entity_id'?: string | undefined; 'process.session_leader.parent.pid'?: string | number | undefined; 'process.session_leader.parent.session_leader.entity_id'?: string | undefined; 'process.session_leader.parent.session_leader.pid'?: string | number | undefined; 'process.session_leader.parent.session_leader.start'?: string | number | undefined; 'process.session_leader.parent.session_leader.vpid'?: string | number | undefined; 'process.session_leader.parent.start'?: string | number | undefined; 'process.session_leader.parent.vpid'?: string | number | undefined; 'process.session_leader.pid'?: string | number | undefined; 'process.session_leader.real_group.id'?: string | undefined; 'process.session_leader.real_group.name'?: string | undefined; 'process.session_leader.real_user.id'?: string | undefined; 'process.session_leader.real_user.name'?: string | undefined; 'process.session_leader.same_as_process'?: boolean | undefined; 'process.session_leader.saved_group.id'?: string | undefined; 'process.session_leader.saved_group.name'?: string | undefined; 'process.session_leader.saved_user.id'?: string | undefined; 'process.session_leader.saved_user.name'?: string | undefined; 'process.session_leader.start'?: string | number | undefined; 'process.session_leader.supplemental_groups.id'?: string | undefined; 'process.session_leader.supplemental_groups.name'?: string | undefined; 'process.session_leader.tty'?: unknown; 'process.session_leader.user.id'?: string | undefined; 'process.session_leader.user.name'?: string | undefined; 'process.session_leader.vpid'?: string | number | undefined; 'process.session_leader.working_directory'?: string | undefined; 'process.start'?: string | number | undefined; 'process.supplemental_groups.id'?: string | undefined; 'process.supplemental_groups.name'?: string | undefined; 'process.thread.capabilities.effective'?: string[] | undefined; 'process.thread.capabilities.permitted'?: string[] | undefined; 'process.thread.id'?: string | number | undefined; 'process.thread.name'?: string | undefined; 'process.title'?: string | undefined; 'process.tty'?: unknown; 'process.uptime'?: string | number | undefined; 'process.user.id'?: string | undefined; 'process.user.name'?: string | undefined; 'process.vpid'?: string | number | undefined; 'process.working_directory'?: string | undefined; 'registry.data.bytes'?: string | undefined; 'registry.data.strings'?: string[] | undefined; 'registry.data.type'?: string | undefined; 'registry.hive'?: string | undefined; 'registry.key'?: string | undefined; 'registry.path'?: string | undefined; 'registry.value'?: string | undefined; 'related.hash'?: string[] | undefined; 'related.hosts'?: string[] | undefined; 'related.ip'?: string[] | undefined; 'related.user'?: string[] | undefined; 'rule.author'?: string[] | undefined; 'rule.category'?: string | undefined; 'rule.description'?: string | undefined; 'rule.id'?: string | undefined; 'rule.license'?: string | undefined; 'rule.name'?: string | undefined; 'rule.reference'?: string | undefined; 'rule.ruleset'?: string | undefined; 'rule.uuid'?: string | undefined; 'rule.version'?: string | undefined; 'server.address'?: string | undefined; 'server.as.number'?: string | number | undefined; 'server.as.organization.name'?: string | undefined; 'server.bytes'?: string | number | undefined; 'server.domain'?: string | undefined; 'server.geo.city_name'?: string | undefined; 'server.geo.continent_code'?: string | undefined; 'server.geo.continent_name'?: string | undefined; 'server.geo.country_iso_code'?: string | undefined; 'server.geo.country_name'?: string | undefined; 'server.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'server.geo.name'?: string | undefined; 'server.geo.postal_code'?: string | undefined; 'server.geo.region_iso_code'?: string | undefined; 'server.geo.region_name'?: string | undefined; 'server.geo.timezone'?: string | undefined; 'server.ip'?: string | undefined; 'server.mac'?: string | undefined; 'server.nat.ip'?: string | undefined; 'server.nat.port'?: string | number | undefined; 'server.packets'?: string | number | undefined; 'server.port'?: string | number | undefined; 'server.registered_domain'?: string | undefined; 'server.subdomain'?: string | undefined; 'server.top_level_domain'?: string | undefined; 'server.user.domain'?: string | undefined; 'server.user.email'?: string | undefined; 'server.user.full_name'?: string | undefined; 'server.user.group.domain'?: string | undefined; 'server.user.group.id'?: string | undefined; 'server.user.group.name'?: string | undefined; 'server.user.hash'?: string | undefined; 'server.user.id'?: string | undefined; 'server.user.name'?: string | undefined; 'server.user.roles'?: string[] | undefined; 'service.address'?: string | undefined; 'service.environment'?: string | undefined; 'service.ephemeral_id'?: string | undefined; 'service.id'?: string | undefined; 'service.name'?: string | undefined; 'service.node.name'?: string | undefined; 'service.node.role'?: string | undefined; 'service.node.roles'?: string[] | undefined; 'service.origin.address'?: string | undefined; 'service.origin.environment'?: string | undefined; 'service.origin.ephemeral_id'?: string | undefined; 'service.origin.id'?: string | undefined; 'service.origin.name'?: string | undefined; 'service.origin.node.name'?: string | undefined; 'service.origin.node.role'?: string | undefined; 'service.origin.node.roles'?: string[] | undefined; 'service.origin.state'?: string | undefined; 'service.origin.type'?: string | undefined; 'service.origin.version'?: string | undefined; 'service.state'?: string | undefined; 'service.target.address'?: string | undefined; 'service.target.environment'?: string | undefined; 'service.target.ephemeral_id'?: string | undefined; 'service.target.id'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.node.name'?: string | undefined; 'service.target.node.role'?: string | undefined; 'service.target.node.roles'?: string[] | undefined; 'service.target.state'?: string | undefined; 'service.target.type'?: string | undefined; 'service.target.version'?: string | undefined; 'service.type'?: string | undefined; 'service.version'?: string | undefined; 'source.address'?: string | undefined; 'source.as.number'?: string | number | undefined; 'source.as.organization.name'?: string | undefined; 'source.bytes'?: string | number | undefined; 'source.domain'?: string | undefined; 'source.geo.city_name'?: string | undefined; 'source.geo.continent_code'?: string | undefined; 'source.geo.continent_name'?: string | undefined; 'source.geo.country_iso_code'?: string | undefined; 'source.geo.country_name'?: string | undefined; 'source.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'source.geo.name'?: string | undefined; 'source.geo.postal_code'?: string | undefined; 'source.geo.region_iso_code'?: string | undefined; 'source.geo.region_name'?: string | undefined; 'source.geo.timezone'?: string | undefined; 'source.ip'?: string | undefined; 'source.mac'?: string | undefined; 'source.nat.ip'?: string | undefined; 'source.nat.port'?: string | number | undefined; 'source.packets'?: string | number | undefined; 'source.port'?: string | number | undefined; 'source.registered_domain'?: string | undefined; 'source.subdomain'?: string | undefined; 'source.top_level_domain'?: string | undefined; 'source.user.domain'?: string | undefined; 'source.user.email'?: string | undefined; 'source.user.full_name'?: string | undefined; 'source.user.group.domain'?: string | undefined; 'source.user.group.id'?: string | undefined; 'source.user.group.name'?: string | undefined; 'source.user.hash'?: string | undefined; 'source.user.id'?: string | undefined; 'source.user.name'?: string | undefined; 'source.user.roles'?: string[] | undefined; 'span.id'?: string | undefined; tags?: string[] | undefined; 'threat.enrichments'?: { indicator?: unknown; 'matched.atomic'?: string | undefined; 'matched.field'?: string | undefined; 'matched.id'?: string | undefined; 'matched.index'?: string | undefined; 'matched.occurred'?: string | number | undefined; 'matched.type'?: string | undefined; }[] | undefined; 'threat.feed.dashboard_id'?: string | undefined; 'threat.feed.description'?: string | undefined; 'threat.feed.name'?: string | undefined; 'threat.feed.reference'?: string | undefined; 'threat.framework'?: string | undefined; 'threat.group.alias'?: string[] | undefined; 'threat.group.id'?: string | undefined; 'threat.group.name'?: string | undefined; 'threat.group.reference'?: string | undefined; 'threat.indicator.as.number'?: string | number | undefined; 'threat.indicator.as.organization.name'?: string | undefined; 'threat.indicator.confidence'?: string | undefined; 'threat.indicator.description'?: string | undefined; 'threat.indicator.email.address'?: string | undefined; 'threat.indicator.file.accessed'?: string | number | undefined; 'threat.indicator.file.attributes'?: string[] | undefined; 'threat.indicator.file.code_signature.digest_algorithm'?: string | undefined; 'threat.indicator.file.code_signature.exists'?: boolean | undefined; 'threat.indicator.file.code_signature.signing_id'?: string | undefined; 'threat.indicator.file.code_signature.status'?: string | undefined; 'threat.indicator.file.code_signature.subject_name'?: string | undefined; 'threat.indicator.file.code_signature.team_id'?: string | undefined; 'threat.indicator.file.code_signature.timestamp'?: string | number | undefined; 'threat.indicator.file.code_signature.trusted'?: boolean | undefined; 'threat.indicator.file.code_signature.valid'?: boolean | undefined; 'threat.indicator.file.created'?: string | number | undefined; 'threat.indicator.file.ctime'?: string | number | undefined; 'threat.indicator.file.device'?: string | undefined; 'threat.indicator.file.directory'?: string | undefined; 'threat.indicator.file.drive_letter'?: string | undefined; 'threat.indicator.file.elf.architecture'?: string | undefined; 'threat.indicator.file.elf.byte_order'?: string | undefined; 'threat.indicator.file.elf.cpu_type'?: string | undefined; 'threat.indicator.file.elf.creation_date'?: string | number | undefined; 'threat.indicator.file.elf.exports'?: unknown[] | undefined; 'threat.indicator.file.elf.go_import_hash'?: string | undefined; 'threat.indicator.file.elf.go_imports'?: unknown; 'threat.indicator.file.elf.go_imports_names_entropy'?: string | number | undefined; 'threat.indicator.file.elf.go_imports_names_var_entropy'?: string | number | undefined; 'threat.indicator.file.elf.go_stripped'?: boolean | undefined; 'threat.indicator.file.elf.header.abi_version'?: string | undefined; 'threat.indicator.file.elf.header.class'?: string | undefined; 'threat.indicator.file.elf.header.data'?: string | undefined; 'threat.indicator.file.elf.header.entrypoint'?: string | number | undefined; 'threat.indicator.file.elf.header.object_version'?: string | undefined; 'threat.indicator.file.elf.header.os_abi'?: string | undefined; 'threat.indicator.file.elf.header.type'?: string | undefined; 'threat.indicator.file.elf.header.version'?: string | undefined; 'threat.indicator.file.elf.import_hash'?: string | undefined; 'threat.indicator.file.elf.imports'?: unknown[] | undefined; 'threat.indicator.file.elf.imports_names_entropy'?: string | number | undefined; 'threat.indicator.file.elf.imports_names_var_entropy'?: string | number | undefined; 'threat.indicator.file.elf.sections'?: { chi2?: string | number | undefined; entropy?: string | number | undefined; flags?: string | undefined; name?: string | undefined; physical_offset?: string | undefined; physical_size?: string | number | undefined; type?: string | undefined; var_entropy?: string | number | undefined; virtual_address?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'threat.indicator.file.elf.segments'?: { sections?: string | undefined; type?: string | undefined; }[] | undefined; 'threat.indicator.file.elf.shared_libraries'?: string[] | undefined; 'threat.indicator.file.elf.telfhash'?: string | undefined; 'threat.indicator.file.extension'?: string | undefined; 'threat.indicator.file.fork_name'?: string | undefined; 'threat.indicator.file.gid'?: string | undefined; 'threat.indicator.file.group'?: string | undefined; 'threat.indicator.file.hash.md5'?: string | undefined; 'threat.indicator.file.hash.sha1'?: string | undefined; 'threat.indicator.file.hash.sha256'?: string | undefined; 'threat.indicator.file.hash.sha384'?: string | undefined; 'threat.indicator.file.hash.sha512'?: string | undefined; 'threat.indicator.file.hash.ssdeep'?: string | undefined; 'threat.indicator.file.hash.tlsh'?: string | undefined; 'threat.indicator.file.inode'?: string | undefined; 'threat.indicator.file.mime_type'?: string | undefined; 'threat.indicator.file.mode'?: string | undefined; 'threat.indicator.file.mtime'?: string | number | undefined; 'threat.indicator.file.name'?: string | undefined; 'threat.indicator.file.owner'?: string | undefined; 'threat.indicator.file.path'?: string | undefined; 'threat.indicator.file.pe.architecture'?: string | undefined; 'threat.indicator.file.pe.company'?: string | undefined; 'threat.indicator.file.pe.description'?: string | undefined; 'threat.indicator.file.pe.file_version'?: string | undefined; 'threat.indicator.file.pe.go_import_hash'?: string | undefined; 'threat.indicator.file.pe.go_imports'?: unknown; 'threat.indicator.file.pe.go_imports_names_entropy'?: string | number | undefined; 'threat.indicator.file.pe.go_imports_names_var_entropy'?: string | number | undefined; 'threat.indicator.file.pe.go_stripped'?: boolean | undefined; 'threat.indicator.file.pe.imphash'?: string | undefined; 'threat.indicator.file.pe.import_hash'?: string | undefined; 'threat.indicator.file.pe.imports'?: unknown[] | undefined; 'threat.indicator.file.pe.imports_names_entropy'?: string | number | undefined; 'threat.indicator.file.pe.imports_names_var_entropy'?: string | number | undefined; 'threat.indicator.file.pe.original_file_name'?: string | undefined; 'threat.indicator.file.pe.pehash'?: string | undefined; 'threat.indicator.file.pe.product'?: string | undefined; 'threat.indicator.file.pe.sections'?: { entropy?: string | number | undefined; name?: string | undefined; physical_size?: string | number | undefined; var_entropy?: string | number | undefined; virtual_size?: string | number | undefined; }[] | undefined; 'threat.indicator.file.size'?: string | number | undefined; 'threat.indicator.file.target_path'?: string | undefined; 'threat.indicator.file.type'?: string | undefined; 'threat.indicator.file.uid'?: string | undefined; 'threat.indicator.file.x509.alternative_names'?: string[] | undefined; 'threat.indicator.file.x509.issuer.common_name'?: string[] | undefined; 'threat.indicator.file.x509.issuer.country'?: string[] | undefined; 'threat.indicator.file.x509.issuer.distinguished_name'?: string | undefined; 'threat.indicator.file.x509.issuer.locality'?: string[] | undefined; 'threat.indicator.file.x509.issuer.organization'?: string[] | undefined; 'threat.indicator.file.x509.issuer.organizational_unit'?: string[] | undefined; 'threat.indicator.file.x509.issuer.state_or_province'?: string[] | undefined; 'threat.indicator.file.x509.not_after'?: string | number | undefined; 'threat.indicator.file.x509.not_before'?: string | number | undefined; 'threat.indicator.file.x509.public_key_algorithm'?: string | undefined; 'threat.indicator.file.x509.public_key_curve'?: string | undefined; 'threat.indicator.file.x509.public_key_exponent'?: string | number | undefined; 'threat.indicator.file.x509.public_key_size'?: string | number | undefined; 'threat.indicator.file.x509.serial_number'?: string | undefined; 'threat.indicator.file.x509.signature_algorithm'?: string | undefined; 'threat.indicator.file.x509.subject.common_name'?: string[] | undefined; 'threat.indicator.file.x509.subject.country'?: string[] | undefined; 'threat.indicator.file.x509.subject.distinguished_name'?: string | undefined; 'threat.indicator.file.x509.subject.locality'?: string[] | undefined; 'threat.indicator.file.x509.subject.organization'?: string[] | undefined; 'threat.indicator.file.x509.subject.organizational_unit'?: string[] | undefined; 'threat.indicator.file.x509.subject.state_or_province'?: string[] | undefined; 'threat.indicator.file.x509.version_number'?: string | undefined; 'threat.indicator.first_seen'?: string | number | undefined; 'threat.indicator.geo.city_name'?: string | undefined; 'threat.indicator.geo.continent_code'?: string | undefined; 'threat.indicator.geo.continent_name'?: string | undefined; 'threat.indicator.geo.country_iso_code'?: string | undefined; 'threat.indicator.geo.country_name'?: string | undefined; 'threat.indicator.geo.location'?: string | { type: string; coordinates: number[]; } | { lat: number; lon: number; } | { location: number[]; } | { location: string; } | undefined; 'threat.indicator.geo.name'?: string | undefined; 'threat.indicator.geo.postal_code'?: string | undefined; 'threat.indicator.geo.region_iso_code'?: string | undefined; 'threat.indicator.geo.region_name'?: string | undefined; 'threat.indicator.geo.timezone'?: string | undefined; 'threat.indicator.ip'?: string | undefined; 'threat.indicator.last_seen'?: string | number | undefined; 'threat.indicator.marking.tlp'?: string | undefined; 'threat.indicator.marking.tlp_version'?: string | undefined; 'threat.indicator.modified_at'?: string | number | undefined; 'threat.indicator.name'?: string | undefined; 'threat.indicator.port'?: string | number | undefined; 'threat.indicator.provider'?: string | undefined; 'threat.indicator.reference'?: string | undefined; 'threat.indicator.registry.data.bytes'?: string | undefined; 'threat.indicator.registry.data.strings'?: string[] | undefined; 'threat.indicator.registry.data.type'?: string | undefined; 'threat.indicator.registry.hive'?: string | undefined; 'threat.indicator.registry.key'?: string | undefined; 'threat.indicator.registry.path'?: string | undefined; 'threat.indicator.registry.value'?: string | undefined; 'threat.indicator.scanner_stats'?: string | number | undefined; 'threat.indicator.sightings'?: string | number | undefined; 'threat.indicator.type'?: string | undefined; 'threat.indicator.url.domain'?: string | undefined; 'threat.indicator.url.extension'?: string | undefined; 'threat.indicator.url.fragment'?: string | undefined; 'threat.indicator.url.full'?: string | undefined; 'threat.indicator.url.original'?: string | undefined; 'threat.indicator.url.password'?: string | undefined; 'threat.indicator.url.path'?: string | undefined; 'threat.indicator.url.port'?: string | number | undefined; 'threat.indicator.url.query'?: string | undefined; 'threat.indicator.url.registered_domain'?: string | undefined; 'threat.indicator.url.scheme'?: string | undefined; 'threat.indicator.url.subdomain'?: string | undefined; 'threat.indicator.url.top_level_domain'?: string | undefined; 'threat.indicator.url.username'?: string | undefined; 'threat.indicator.x509.alternative_names'?: string[] | undefined; 'threat.indicator.x509.issuer.common_name'?: string[] | undefined; 'threat.indicator.x509.issuer.country'?: string[] | undefined; 'threat.indicator.x509.issuer.distinguished_name'?: string | undefined; 'threat.indicator.x509.issuer.locality'?: string[] | undefined; 'threat.indicator.x509.issuer.organization'?: string[] | undefined; 'threat.indicator.x509.issuer.organizational_unit'?: string[] | undefined; 'threat.indicator.x509.issuer.state_or_province'?: string[] | undefined; 'threat.indicator.x509.not_after'?: string | number | undefined; 'threat.indicator.x509.not_before'?: string | number | undefined; 'threat.indicator.x509.public_key_algorithm'?: string | undefined; 'threat.indicator.x509.public_key_curve'?: string | undefined; 'threat.indicator.x509.public_key_exponent'?: string | number | undefined; 'threat.indicator.x509.public_key_size'?: string | number | undefined; 'threat.indicator.x509.serial_number'?: string | undefined; 'threat.indicator.x509.signature_algorithm'?: string | undefined; 'threat.indicator.x509.subject.common_name'?: string[] | undefined; 'threat.indicator.x509.subject.country'?: string[] | undefined; 'threat.indicator.x509.subject.distinguished_name'?: string | undefined; 'threat.indicator.x509.subject.locality'?: string[] | undefined; 'threat.indicator.x509.subject.organization'?: string[] | undefined; 'threat.indicator.x509.subject.organizational_unit'?: string[] | undefined; 'threat.indicator.x509.subject.state_or_province'?: string[] | undefined; 'threat.indicator.x509.version_number'?: string | undefined; 'threat.software.alias'?: string[] | undefined; 'threat.software.id'?: string | undefined; 'threat.software.name'?: string | undefined; 'threat.software.platforms'?: string[] | undefined; 'threat.software.reference'?: string | undefined; 'threat.software.type'?: string | undefined; 'threat.tactic.id'?: string[] | undefined; 'threat.tactic.name'?: string[] | undefined; 'threat.tactic.reference'?: string[] | undefined; 'threat.technique.id'?: string[] | undefined; 'threat.technique.name'?: string[] | undefined; 'threat.technique.reference'?: string[] | undefined; 'threat.technique.subtechnique.id'?: string[] | undefined; 'threat.technique.subtechnique.name'?: string[] | undefined; 'threat.technique.subtechnique.reference'?: string[] | undefined; 'tls.cipher'?: string | undefined; 'tls.client.certificate'?: string | undefined; 'tls.client.certificate_chain'?: string[] | undefined; 'tls.client.hash.md5'?: string | undefined; 'tls.client.hash.sha1'?: string | undefined; 'tls.client.hash.sha256'?: string | undefined; 'tls.client.issuer'?: string | undefined; 'tls.client.ja3'?: string | undefined; 'tls.client.not_after'?: string | number | undefined; 'tls.client.not_before'?: string | number | undefined; 'tls.client.server_name'?: string | undefined; 'tls.client.subject'?: string | undefined; 'tls.client.supported_ciphers'?: string[] | undefined; 'tls.client.x509.alternative_names'?: string[] | undefined; 'tls.client.x509.issuer.common_name'?: string[] | undefined; 'tls.client.x509.issuer.country'?: string[] | undefined; 'tls.client.x509.issuer.distinguished_name'?: string | undefined; 'tls.client.x509.issuer.locality'?: string[] | undefined; 'tls.client.x509.issuer.organization'?: string[] | undefined; 'tls.client.x509.issuer.organizational_unit'?: string[] | undefined; 'tls.client.x509.issuer.state_or_province'?: string[] | undefined; 'tls.client.x509.not_after'?: string | number | undefined; 'tls.client.x509.not_before'?: string | number | undefined; 'tls.client.x509.public_key_algorithm'?: string | undefined; 'tls.client.x509.public_key_curve'?: string | undefined; 'tls.client.x509.public_key_exponent'?: string | number | undefined; 'tls.client.x509.public_key_size'?: string | number | undefined; 'tls.client.x509.serial_number'?: string | undefined; 'tls.client.x509.signature_algorithm'?: string | undefined; 'tls.client.x509.subject.common_name'?: string[] | undefined; 'tls.client.x509.subject.country'?: string[] | undefined; 'tls.client.x509.subject.distinguished_name'?: string | undefined; 'tls.client.x509.subject.locality'?: string[] | undefined; 'tls.client.x509.subject.organization'?: string[] | undefined; 'tls.client.x509.subject.organizational_unit'?: string[] | undefined; 'tls.client.x509.subject.state_or_province'?: string[] | undefined; 'tls.client.x509.version_number'?: string | undefined; 'tls.curve'?: string | undefined; 'tls.established'?: boolean | undefined; 'tls.next_protocol'?: string | undefined; 'tls.resumed'?: boolean | undefined; 'tls.server.certificate'?: string | undefined; 'tls.server.certificate_chain'?: string[] | undefined; 'tls.server.hash.md5'?: string | undefined; 'tls.server.hash.sha1'?: string | undefined; 'tls.server.hash.sha256'?: string | undefined; 'tls.server.issuer'?: string | undefined; 'tls.server.ja3s'?: string | undefined; 'tls.server.not_after'?: string | number | undefined; 'tls.server.not_before'?: string | number | undefined; 'tls.server.subject'?: string | undefined; 'tls.server.x509.alternative_names'?: string[] | undefined; 'tls.server.x509.issuer.common_name'?: string[] | undefined; 'tls.server.x509.issuer.country'?: string[] | undefined; 'tls.server.x509.issuer.distinguished_name'?: string | undefined; 'tls.server.x509.issuer.locality'?: string[] | undefined; 'tls.server.x509.issuer.organization'?: string[] | undefined; 'tls.server.x509.issuer.organizational_unit'?: string[] | undefined; 'tls.server.x509.issuer.state_or_province'?: string[] | undefined; 'tls.server.x509.not_after'?: string | number | undefined; 'tls.server.x509.not_before'?: string | number | undefined; 'tls.server.x509.public_key_algorithm'?: string | undefined; 'tls.server.x509.public_key_curve'?: string | undefined; 'tls.server.x509.public_key_exponent'?: string | number | undefined; 'tls.server.x509.public_key_size'?: string | number | undefined; 'tls.server.x509.serial_number'?: string | undefined; 'tls.server.x509.signature_algorithm'?: string | undefined; 'tls.server.x509.subject.common_name'?: string[] | undefined; 'tls.server.x509.subject.country'?: string[] | undefined; 'tls.server.x509.subject.distinguished_name'?: string | undefined; 'tls.server.x509.subject.locality'?: string[] | undefined; 'tls.server.x509.subject.organization'?: string[] | undefined; 'tls.server.x509.subject.organizational_unit'?: string[] | undefined; 'tls.server.x509.subject.state_or_province'?: string[] | undefined; 'tls.server.x509.version_number'?: string | undefined; 'tls.version'?: string | undefined; 'tls.version_protocol'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.id'?: string | undefined; 'url.domain'?: string | undefined; 'url.extension'?: string | undefined; 'url.fragment'?: string | undefined; 'url.full'?: string | undefined; 'url.original'?: string | undefined; 'url.password'?: string | undefined; 'url.path'?: string | undefined; 'url.port'?: string | number | undefined; 'url.query'?: string | undefined; 'url.registered_domain'?: string | undefined; 'url.scheme'?: string | undefined; 'url.subdomain'?: string | undefined; 'url.top_level_domain'?: string | undefined; 'url.username'?: string | undefined; 'user.changes.domain'?: string | undefined; 'user.changes.email'?: string | undefined; 'user.changes.full_name'?: string | undefined; 'user.changes.group.domain'?: string | undefined; 'user.changes.group.id'?: string | undefined; 'user.changes.group.name'?: string | undefined; 'user.changes.hash'?: string | undefined; 'user.changes.id'?: string | undefined; 'user.changes.name'?: string | undefined; 'user.changes.roles'?: string[] | undefined; 'user.domain'?: string | undefined; 'user.effective.domain'?: string | undefined; 'user.effective.email'?: string | undefined; 'user.effective.full_name'?: string | undefined; 'user.effective.group.domain'?: string | undefined; 'user.effective.group.id'?: string | undefined; 'user.effective.group.name'?: string | undefined; 'user.effective.hash'?: string | undefined; 'user.effective.id'?: string | undefined; 'user.effective.name'?: string | undefined; 'user.effective.roles'?: string[] | undefined; 'user.email'?: string | undefined; 'user.full_name'?: string | undefined; 'user.group.domain'?: string | undefined; 'user.group.id'?: string | undefined; 'user.group.name'?: string | undefined; 'user.hash'?: string | undefined; 'user.id'?: string | undefined; 'user.name'?: string | undefined; 'user.risk.calculated_level'?: string | undefined; 'user.risk.calculated_score'?: number | undefined; 'user.risk.calculated_score_norm'?: number | undefined; 'user.risk.static_level'?: string | undefined; 'user.risk.static_score'?: number | undefined; 'user.risk.static_score_norm'?: number | undefined; 'user.roles'?: string[] | undefined; 'user.target.domain'?: string | undefined; 'user.target.email'?: string | undefined; 'user.target.full_name'?: string | undefined; 'user.target.group.domain'?: string | undefined; 'user.target.group.id'?: string | undefined; 'user.target.group.name'?: string | undefined; 'user.target.hash'?: string | undefined; 'user.target.id'?: string | undefined; 'user.target.name'?: string | undefined; 'user.target.roles'?: string[] | undefined; 'user_agent.device.name'?: string | undefined; 'user_agent.name'?: string | undefined; 'user_agent.original'?: string | undefined; 'user_agent.os.family'?: string | undefined; 'user_agent.os.full'?: string | undefined; 'user_agent.os.kernel'?: string | undefined; 'user_agent.os.name'?: string | undefined; 'user_agent.os.platform'?: string | undefined; 'user_agent.os.type'?: string | undefined; 'user_agent.os.version'?: string | undefined; 'user_agent.version'?: string | undefined; 'vulnerability.category'?: string[] | undefined; 'vulnerability.classification'?: string | undefined; 'vulnerability.description'?: string | undefined; 'vulnerability.enumeration'?: string | undefined; 'vulnerability.id'?: string | undefined; 'vulnerability.reference'?: string | undefined; 'vulnerability.report_id'?: string | undefined; 'vulnerability.scanner.vendor'?: string | undefined; 'vulnerability.score.base'?: number | undefined; 'vulnerability.score.environmental'?: number | undefined; 'vulnerability.score.temporal'?: number | undefined; 'vulnerability.score.version'?: string | undefined; 'vulnerability.severity'?: string | undefined; }" ], "path": "packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts", "deprecated": false, diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 4abb587516915..d85dceff868c6 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 487d845867b34..035f4691ada4a 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: 2024-06-18 +date: 2024-06-19 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 e46bfe5940a94..a61eec4b3e02c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index 351c1e8690d63..143acf3a461c7 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index d98fbe3570141..f05c565560637 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: 2024-06-18 +date: 2024-06-19 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_data_view.mdx b/api_docs/kbn_apm_data_view.mdx index 307aeb06fe7b0..f414c8a5b9a24 100644 --- a/api_docs/kbn_apm_data_view.mdx +++ b/api_docs/kbn_apm_data_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-data-view title: "@kbn/apm-data-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-data-view plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-data-view'] --- import kbnApmDataViewObj from './kbn_apm_data_view.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index d16fad88bde1c..ad357a4144d50 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: 2024-06-18 +date: 2024-06-19 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 5d4077f25f851..50ece00b8f43b 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: 2024-06-18 +date: 2024-06-19 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 4078b2b992498..f7328138d0261 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: 2024-06-18 +date: 2024-06-19 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 a86bfa4aba3dc..fc15dcbb32bfe 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index dfab0800e2a0f..130c509e6e978 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index a831688cd6a16..4a92028ce2133 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index 56e46c2ac595e..4a731b72de36a 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 88e2fe42a4fec..3649b11cba127 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: 2024-06-18 +date: 2024-06-19 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 43e66d95034f7..aa437b53ef5c5 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: 2024-06-18 +date: 2024-06-19 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 73f3e636779ac..039d4cac81d55 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: 2024-06-18 +date: 2024-06-19 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 a39b164e2e066..8d52987346013 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: 2024-06-18 +date: 2024-06-19 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 7b14acf65b838..c883c4ea501c6 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: 2024-06-18 +date: 2024-06-19 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 ed9607d16f834..4d8d6b6f095db 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: 2024-06-18 +date: 2024-06-19 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 a8c36eed58e93..47a27d830b9b0 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: 2024-06-18 +date: 2024-06-19 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 cf0dac9edba01..9b7d2a0d64912 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: 2024-06-18 +date: 2024-06-19 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 dfa158ac1ec18..0d42b35f0f7e6 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mock.mdx b/api_docs/kbn_code_editor_mock.mdx index 54c2b42c47d0f..6c18c1361f88c 100644 --- a/api_docs/kbn_code_editor_mock.mdx +++ b/api_docs/kbn_code_editor_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mock title: "@kbn/code-editor-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mock plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mock'] --- import kbnCodeEditorMockObj from './kbn_code_editor_mock.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index a4509947484f8..4506e4957f745 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 1ad88c024bbf8..f50fe7d50e1bc 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: 2024-06-18 +date: 2024-06-19 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 9b875d1e2e2ac..971b080bd7600 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: 2024-06-18 +date: 2024-06-19 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 e0e354ab7ad5d..9ac2e856ef23d 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.devdocs.json b/api_docs/kbn_config_schema.devdocs.json index 6b5e7c68c2f26..a78058f053a21 100644 --- a/api_docs/kbn_config_schema.devdocs.json +++ b/api_docs/kbn_config_schema.devdocs.json @@ -1169,9 +1169,11 @@ "type": "Function", "tags": [], "label": "validate", - "description": [], + "description": [ + "\nValidates the provided value against this schema.\nIf valid, the resulting output will be returned, otherwise an exception will be thrown." + ], "signature": [ - "(value: any, context?: Record, namespace?: string | undefined) => V" + "(value: unknown, context?: Record, namespace?: string | undefined) => V" ], "path": "packages/kbn-config-schema/src/types/type.ts", "deprecated": false, @@ -1180,12 +1182,12 @@ { "parentPluginId": "@kbn/config-schema", "id": "def-common.Type.validate.$1", - "type": "Any", + "type": "Unknown", "tags": [], "label": "value", "description": [], "signature": [ - "any" + "unknown" ], "path": "packages/kbn-config-schema/src/types/type.ts", "deprecated": false, @@ -1200,7 +1202,7 @@ "label": "context", "description": [], "signature": [ - "Record" + "Record" ], "path": "packages/kbn-config-schema/src/types/type.ts", "deprecated": false, @@ -1668,213 +1670,185 @@ "label": "Schema", "description": [], "signature": [ - "{ any: (options?: ", - "TypeOptions", - " | undefined) => ", + "{ allOf: { (itemType: ", + ", B extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", options?: ", - "ArrayOptions", - " | undefined) => ", + ", C extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; boolean: (options?: ", - "TypeOptions", - " | undefined) => ", + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; buffer: (options?: ", - "TypeOptions", - " | undefined) => ", + ", E extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; byteSize: (options?: ", - "ByteSizeOptions", - " | undefined) => ", + ", F extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "<", + ", G extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.ByteSizeValue", - "text": "ByteSizeValue" + "section": "def-common.Props", + "text": "Props" }, - ">; conditional: (leftOperand: ", - "Reference", - ", rightOperand: A | ", - "Reference", - " | ", + ", H extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", equalType: ", + ", I extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", notEqualType: ", + ", J extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", options?: ", - "TypeOptions", - " | undefined) => ", + ", K extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.ConditionalType", - "text": "ConditionalType" + "section": "def-common.Props", + "text": "Props" }, - "; contextRef: (key: string) => ", - "ContextReference", - "; duration: (options?: ", - "DurationOptions", - " | undefined) => ", + ">(types: [", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; ip: (options?: ", - "IpOptions", - " | undefined) => ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; lazy: (id: string) => ", - "Lazy", - "; literal: (value: T) => ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; mapOf: (keyType: ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", valueType: ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", options?: ", - "MapOfOptions", - " | undefined) => ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ">; maybe: (type: ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ") => ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; nullable: (type: ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ") => ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; never: () => ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; number: (options?: ", - "NumberOptions", - " | undefined) => ", + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -1882,205 +1856,185 @@ "section": "def-common.Type", "text": "Type" }, - "; object:

]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Props", - "text": "Props" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ">(props: P, options?: ", - "ObjectTypeOptions", - "

| undefined) => ", + "<(A & B & C & D & E & F & G & H & I & J & K)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.ObjectType", - "text": "ObjectType" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - "

; oneOf: { (types: [", + "<(A & B & C & D & E & F & G & H & I & J & K)[K]>; }>>; , ", + ", B extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", C extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", E extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", F extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", G extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", H extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", I extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", J extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ">(types: [", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; (types: [", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - ", ", - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - ", ", - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, "], options?: ", "UnionTypeOptions", - " | undefined): ", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2088,163 +2042,169 @@ "section": "def-common.Type", "text": "Type" }, - "; (types: [", + "]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", ", + "<(A & B & C & D & E & F & G & H & I & J)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", ", + "<(A & B & C & D & E & F & G & H & I & J)[K]>; }>>; , ", + ", B extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", C extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", E extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", F extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", G extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", H extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; (types: [", + ", I extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" + }, + ">(types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; (types: [", + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2252,155 +2212,153 @@ "section": "def-common.Type", "text": "Type" }, - ", ", + "]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", ", + "<(A & B & C & D & E & F & G & H & I)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", ", + "<(A & B & C & D & E & F & G & H & I)[K]>; }>>; , ", + ", B extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", C extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", E extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; (types: [", + ", F extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", G extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", H extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ">(types: [", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; (types: [", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", ", + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2408,85 +2366,137 @@ "section": "def-common.Type", "text": "Type" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + "]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - "; (types: [", + "<(A & B & C & D & E & F & G & H)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", ", + "<(A & B & C & D & E & F & G & H)[K]>; }>>; , ", + "section": "def-common.Props", + "text": "Props" + }, + ", B extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", ", + ", C extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; (types: [", + ", E extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" + }, + ", F extends ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Props", + "text": "Props" + }, + ", G extends ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Props", + "text": "Props" + }, + ">(types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "], options?: ", + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", "UnionTypeOptions", - " | undefined): ", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2494,43 +2504,121 @@ "section": "def-common.Type", "text": "Type" }, - "; (types: [", + "]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" }, ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "], options?: ", - "UnionTypeOptions", - " | undefined): ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "; (types: [", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "], options?: ", + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", "UnionTypeOptions", - " | undefined): ", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2538,257 +2626,5712 @@ "section": "def-common.Type", "text": "Type" }, - "; }; recordOf: (keyType: ", + "]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", valueType: ", + "<(A & B & C & D & E & F)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - ", options?: ", - "RecordOfOptions", - " | undefined) => ", + "<(A & B & C & D & E & F)[K]>; }>>; >; stream: (options?: ", - "TypeOptions", - "<", - "Stream", - "> | undefined) => ", + ", B extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "<", - "Stream", - ">; siblingRef: (key: string) => ", - "SiblingReference", - "; string: (options?: ", - "StringOptions", - " | undefined) => ", + ", C extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; uri: (options?: ", - "URIOptions", - " | undefined) => ", + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - "; }" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.TypeOf", - "type": "Type", - "tags": [], - "label": "TypeOf", - "description": [], - "signature": [ - "RT extends () => ", + ", E extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - " ? ReturnType[\"type\"] : RT extends ", + ">(types: [", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - " ? RT[\"type\"] : never" - ], - "path": "packages/kbn-config-schema/src/types/object_type.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "objects": [ - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.metaFields", - "type": "Object", - "tags": [], - "label": "metaFields", - "description": [], - "signature": [ - "{ readonly META_FIELD_X_OAS_ANY: \"x-oas-any-type\"; readonly META_FIELD_X_OAS_OPTIONAL: \"x-oas-optional\"; readonly META_FIELD_X_OAS_DEPRECATED: \"x-oas-deprecated\"; readonly META_FIELD_X_OAS_MAX_LENGTH: \"x-oas-max-length\"; readonly META_FIELD_X_OAS_MIN_LENGTH: \"x-oas-min-length\"; readonly META_FIELD_X_OAS_GET_ADDITIONAL_PROPERTIES: \"x-oas-get-additional-properties\"; }" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema", - "type": "Object", - "tags": [], - "label": "schema", - "description": [], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + ", ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.any", - "type": "Function", - "tags": [], - "label": "any", - "description": [], - "signature": [ - "(options?: ", - "TypeOptions", - " | undefined) => ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + " | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "; }>>; }; any: (options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.AnyType", + "text": "AnyType" + }, + "; arrayOf: (itemType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", options?: ", + "ArrayOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; boolean: (options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; buffer: (options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; byteSize: (options?: ", + "ByteSizeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + ">; conditional: (leftOperand: ", + "Reference", + ", rightOperand: A | ", + "Reference", + " | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", equalType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", notEqualType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; contextRef: (key: string) => ", + "ContextReference", + "; duration: (options?: ", + "DurationOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; intersection: { (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J & K)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J & K)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + " | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "; }>>; }; ip: (options?: ", + "IpOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; lazy: (id: string) => ", + "Lazy", + "; literal: (value: T) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; mapOf: (keyType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", valueType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", options?: ", + "MapOfOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ">; maybe: (type: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ") => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; nullable: (type: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ") => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; never: () => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; number: (options?: ", + "NumberOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; object:

(props: P, options?: ", + "ObjectTypeOptions", + "

| undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "

; oneOf: { (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }; recordOf: (keyType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", valueType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", options?: ", + "RecordOfOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ">; stream: (options?: ", + "TypeOptions", + "<", + "Stream", + "> | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<", + "Stream", + ">; siblingRef: (key: string) => ", + "SiblingReference", + "; string: (options?: ", + "StringOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; uri: (options?: ", + "URIOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.TypeOf", + "type": "Type", + "tags": [], + "label": "TypeOf", + "description": [], + "signature": [ + "RT extends () => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " ? ReturnType[\"type\"] : RT extends ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " ? RT[\"type\"] : never" + ], + "path": "packages/kbn-config-schema/src/types/object_type.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.metaFields", + "type": "Object", + "tags": [], + "label": "metaFields", + "description": [], + "signature": [ + "{ readonly META_FIELD_X_OAS_ANY: \"x-oas-any-type\"; readonly META_FIELD_X_OAS_OPTIONAL: \"x-oas-optional\"; readonly META_FIELD_X_OAS_DEPRECATED: \"x-oas-deprecated\"; readonly META_FIELD_X_OAS_MAX_LENGTH: \"x-oas-max-length\"; readonly META_FIELD_X_OAS_MIN_LENGTH: \"x-oas-min-length\"; readonly META_FIELD_X_OAS_GET_ADDITIONAL_PROPERTIES: \"x-oas-get-additional-properties\"; }" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.allOf", + "type": "Function", + "tags": [], + "label": "allOf", + "description": [], + "signature": [ + "{ (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J & K)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J & K)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + " | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "; }>>; }" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.any", + "type": "Function", + "tags": [], + "label": "any", + "description": [], + "signature": [ + "(options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.AnyType", + "text": "AnyType" + } + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.any.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "TypeOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.arrayOf", + "type": "Function", + "tags": [], + "label": "arrayOf", + "description": [], + "signature": [ + "(itemType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", options?: ", + "ArrayOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.arrayOf.$1", + "type": "Object", + "tags": [], + "label": "itemType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.arrayOf.$2", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "ArrayOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.boolean", + "type": "Function", + "tags": [], + "label": "boolean", + "description": [], + "signature": [ + "(options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.boolean.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "TypeOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.buffer", + "type": "Function", + "tags": [], + "label": "buffer", + "description": [], + "signature": [ + "(options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.buffer.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "TypeOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.byteSize", + "type": "Function", + "tags": [], + "label": "byteSize", + "description": [], + "signature": [ + "(options?: ", + "ByteSizeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + ">" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.byteSize.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "ByteSizeOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.conditional", + "type": "Function", + "tags": [], + "label": "conditional", + "description": [], + "signature": [ + "(leftOperand: ", + "Reference", + ", rightOperand: A | ", + "Reference", + " | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", equalType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", notEqualType: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + ", options?: ", + "TypeOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.conditional.$1", + "type": "Object", + "tags": [], + "label": "leftOperand", + "description": [], + "signature": [ + "Reference", + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.conditional.$2", + "type": "CompoundType", + "tags": [], + "label": "rightOperand", + "description": [], + "signature": [ + "A | ", + "Reference", + " | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.conditional.$3", + "type": "Object", + "tags": [], + "label": "equalType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.conditional.$4", + "type": "Object", + "tags": [], + "label": "notEqualType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.conditional.$5", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "TypeOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.contextRef", + "type": "Function", + "tags": [], + "label": "contextRef", + "description": [], + "signature": [ + "(key: string) => ", + "ContextReference", + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.contextRef.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.duration", + "type": "Function", + "tags": [], + "label": "duration", + "description": [], + "signature": [ + "(options?: ", + "DurationOptions", + " | undefined) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.duration.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "DurationOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.schema.intersection", + "type": "Function", + "tags": [], + "label": "intersection", + "description": [], + "signature": [ + "{ (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J & K)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J & K)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I & J)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H & I)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G & H)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F & G)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E & F)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "]?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D & E)[K]>; }>>; | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.arrayOf", - "type": "Function", - "tags": [], - "label": "arrayOf", - "description": [], - "signature": [ - "(itemType: ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Props", + "text": "Props" + }, + ", D extends ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.Props", + "text": "Props" }, - ", options?: ", - "ArrayOptions", - " | undefined) => ", + ">(types: [", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ + ", ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.arrayOf.$1", - "type": "Object", - "tags": [], - "label": "itemType", - "description": [], - "signature": [ - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" }, + ", ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.arrayOf.$2", - "type": "CompoundType", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "ArrayOptions", - " | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.boolean", - "type": "Function", - "tags": [], - "label": "boolean", - "description": [], - "signature": [ - "(options?: ", - "TypeOptions", - " | undefined) => ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2796,41 +8339,73 @@ "section": "def-common.Type", "text": "Type" }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ + "]?: ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.boolean.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "TypeOptions", - " | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.buffer", - "type": "Function", - "tags": [], - "label": "buffer", - "description": [], - "signature": [ - "(options?: ", - "TypeOptions", - " | undefined) => ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C & D)[K]>; }>>; (types: [", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + ", ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2838,111 +8413,57 @@ "section": "def-common.Type", "text": "Type" }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ + "]?: ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.buffer.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "TypeOptions", - " | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.byteSize", - "type": "Function", - "tags": [], - "label": "byteSize", - "description": [], - "signature": [ - "(options?: ", - "ByteSizeOptions", - " | undefined) => ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + "<(A & B & C)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - "<", + "<(A & B & C)[K]>; }>>; " - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ + ", B extends ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.byteSize.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "ByteSizeOptions", - " | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.conditional", - "type": "Function", - "tags": [], - "label": "conditional", - "description": [], - "signature": [ - "(leftOperand: ", - "Reference", - ", rightOperand: A | ", - "Reference", - " | ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Props", + "text": "Props" + }, + ">(types: [", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", equalType: ", + ", ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.ObjectType", + "text": "ObjectType" }, - ", notEqualType: ", + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -2950,192 +8471,69 @@ "section": "def-common.Type", "text": "Type" }, - ", options?: ", - "TypeOptions", - " | undefined) => ", + "]?: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.ConditionalType", - "text": "ConditionalType" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ + "<(A & B)[K]> | undefined; } & { [K in keyof RequiredProperties]: ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.conditional.$1", - "type": "Object", - "tags": [], - "label": "leftOperand", - "description": [], - "signature": [ - "Reference", - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" }, + "<(A & B)[K]>; }>>; | ", - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Props", + "text": "Props" }, + ">(types: [", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.conditional.$3", - "type": "Object", - "tags": [], - "label": "equalType", - "description": [], - "signature": [ - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" }, + "], options?: ", + "UnionTypeOptions", + " | undefined): ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.conditional.$4", - "type": "Object", - "tags": [], - "label": "notEqualType", - "description": [], - "signature": [ - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" }, + "]?: ", { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.conditional.$5", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "TypeOptions", - " | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.contextRef", - "type": "Function", - "tags": [], - "label": "contextRef", - "description": [], - "signature": [ - "(key: string) => ", - "ContextReference", - "" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.contextRef.$1", - "type": "string", - "tags": [], - "label": "key", - "description": [], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.duration", - "type": "Function", - "tags": [], - "label": "duration", - "description": [], - "signature": [ - "(options?: ", - "DurationOptions", - " | undefined) => ", + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.TypeOf", + "text": "TypeOf" + }, + " | undefined; } & { [K in keyof RequiredProperties]: ", { "pluginId": "@kbn/config-schema", "scope": "common", "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" + "section": "def-common.TypeOf", + "text": "TypeOf" }, - "" + "; }>>; }" ], "path": "packages/kbn-config-schema/index.ts", "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/config-schema", - "id": "def-common.schema.duration.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "DurationOptions", - " | undefined" - ], - "path": "packages/kbn-config-schema/index.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "trackAdoption": false }, { "parentPluginId": "@kbn/config-schema", diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index bb15023427226..7eb1ba384b302 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.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 | |-------------------|-----------|------------------------|-----------------| -| 144 | 3 | 141 | 20 | +| 146 | 2 | 142 | 20 | ## Common diff --git a/api_docs/kbn_content_management_content_editor.devdocs.json b/api_docs/kbn_content_management_content_editor.devdocs.json index b8650daee4eb8..c6144ff95f63b 100644 --- a/api_docs/kbn_content_management_content_editor.devdocs.json +++ b/api_docs/kbn_content_management_content_editor.devdocs.json @@ -186,7 +186,7 @@ "Item", "; isReadonly?: boolean | undefined; readonlyReason?: string | undefined; entityName: string; customValidators?: ", "CustomValidators", - " | undefined; }" + " | undefined; showActivityView?: boolean | undefined; }" ], "path": "packages/content-management/content_editor/src/open_content_editor.tsx", "deprecated": false, diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 37dd4c0061cc2..11d11e8c99e80 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: 2024-06-18 +date: 2024-06-19 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_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index b472318320313..b8c232f7bda68 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index 5b851e5384110..8edb473e68481 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.devdocs.json b/api_docs/kbn_content_management_table_list_view_common.devdocs.json index 61f11d1c921f8..8bf94c542f624 100644 --- a/api_docs/kbn_content_management_table_list_view_common.devdocs.json +++ b/api_docs/kbn_content_management_table_list_view_common.devdocs.json @@ -53,6 +53,34 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/content-management-table-list-view-common", + "id": "def-common.UserContentCommonSchema.updatedBy", + "type": "string", + "tags": [], + "label": "updatedBy", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/content-management/table_list_view_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/content-management-table-list-view-common", + "id": "def-common.UserContentCommonSchema.createdAt", + "type": "string", + "tags": [], + "label": "createdAt", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/content-management/table_list_view_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/content-management-table-list-view-common", "id": "def-common.UserContentCommonSchema.createdBy", diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index eaacdb815fed9..d318908661959 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.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 | |-------------------|-----------|------------------------|-----------------| -| 8 | 0 | 8 | 0 | +| 10 | 0 | 10 | 0 | ## Common diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index b204e4dbf8374..0ac0ed64beb77 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_user_profiles.devdocs.json b/api_docs/kbn_content_management_user_profiles.devdocs.json new file mode 100644 index 0000000000000..0107a179f3ac0 --- /dev/null +++ b/api_docs/kbn_content_management_user_profiles.devdocs.json @@ -0,0 +1,622 @@ +{ + "id": "@kbn/content-management-user-profiles", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.ManagedAvatarTip", + "type": "Function", + "tags": [], + "label": "ManagedAvatarTip", + "description": [], + "signature": [ + "({\n entityName = i18n.translate('contentManagement.userProfiles.managedAvatarTip.defaultEntityName', {\n defaultMessage: 'object',\n }),\n}: { entityName?: string | undefined; }) => JSX.Element" + ], + "path": "packages/content-management/user_profiles/src/components/managed_avatar_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.ManagedAvatarTip.$1", + "type": "Object", + "tags": [], + "label": "{\n entityName = i18n.translate('contentManagement.userProfiles.managedAvatarTip.defaultEntityName', {\n defaultMessage: 'object',\n }),\n}", + "description": [], + "path": "packages/content-management/user_profiles/src/components/managed_avatar_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.ManagedAvatarTip.$1.entityName", + "type": "string", + "tags": [], + "label": "entityName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/content-management/user_profiles/src/components/managed_avatar_tip.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.NoCreatorTip", + "type": "Function", + "tags": [], + "label": "NoCreatorTip", + "description": [], + "signature": [ + "(props: { iconType?: ", + "IconType", + " | undefined; }) => JSX.Element" + ], + "path": "packages/content-management/user_profiles/src/components/user_missing_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.NoCreatorTip.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "path": "packages/content-management/user_profiles/src/components/user_missing_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.NoCreatorTip.$1.iconType", + "type": "CompoundType", + "tags": [], + "label": "iconType", + "description": [], + "signature": [ + "IconType", + " | undefined" + ], + "path": "packages/content-management/user_profiles/src/components/user_missing_tip.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.NoUpdaterTip", + "type": "Function", + "tags": [], + "label": "NoUpdaterTip", + "description": [], + "signature": [ + "(props: { iconType?: string | undefined; }) => JSX.Element" + ], + "path": "packages/content-management/user_profiles/src/components/user_missing_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.NoUpdaterTip.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "path": "packages/content-management/user_profiles/src/components/user_missing_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.NoUpdaterTip.$1.iconType", + "type": "string", + "tags": [], + "label": "iconType", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/content-management/user_profiles/src/components/user_missing_tip.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserAvatarTip", + "type": "Function", + "tags": [], + "label": "UserAvatarTip", + "description": [], + "signature": [ + "(props: { uid: string; }) => JSX.Element | null" + ], + "path": "packages/content-management/user_profiles/src/components/user_avatar_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserAvatarTip.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "path": "packages/content-management/user_profiles/src/components/user_avatar_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserAvatarTip.$1.uid", + "type": "string", + "tags": [], + "label": "uid", + "description": [], + "path": "packages/content-management/user_profiles/src/components/user_avatar_tip.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesKibanaProvider", + "type": "Function", + "tags": [], + "label": "UserProfilesKibanaProvider", + "description": [], + "signature": [ + "({ children, core, }: React.PropsWithChildren>) => JSX.Element" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesKibanaProvider.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n children,\n core,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren>" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesProvider", + "type": "Function", + "tags": [], + "label": "UserProfilesProvider", + "description": [], + "signature": [ + "({ children, ...services }: React.PropsWithChildren>) => JSX.Element" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesProvider.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n children,\n ...services\n}", + "description": [], + "signature": [ + "React.PropsWithChildren>" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfile", + "type": "Function", + "tags": [], + "label": "useUserProfile", + "description": [], + "signature": [ + "(uid: string) => ", + "UseQueryResult", + "<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfile", + "text": "UserProfile" + }, + "<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfileData", + "text": "UserProfileData" + }, + ">, unknown>" + ], + "path": "packages/content-management/user_profiles/src/queries.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfile.$1", + "type": "string", + "tags": [], + "label": "uid", + "description": [], + "signature": [ + "string" + ], + "path": "packages/content-management/user_profiles/src/queries.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfiles", + "type": "Function", + "tags": [], + "label": "useUserProfiles", + "description": [], + "signature": [ + "(uids: string[], opts?: { enabled?: boolean | undefined; } | undefined) => ", + "UseQueryResult", + "<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfile", + "text": "UserProfile" + }, + "<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfileData", + "text": "UserProfileData" + }, + ">[], unknown>" + ], + "path": "packages/content-management/user_profiles/src/queries.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfiles.$1", + "type": "Array", + "tags": [], + "label": "uids", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/content-management/user_profiles/src/queries.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfiles.$2", + "type": "Object", + "tags": [], + "label": "opts", + "description": [], + "path": "packages/content-management/user_profiles/src/queries.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfiles.$2.enabled", + "type": "CompoundType", + "tags": [], + "label": "enabled", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/content-management/user_profiles/src/queries.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.useUserProfilesServices", + "type": "Function", + "tags": [], + "label": "useUserProfilesServices", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/content-management-user-profiles", + "scope": "common", + "docId": "kibKbnContentManagementUserProfilesPluginApi", + "section": "def-common.UserProfilesServices", + "text": "UserProfilesServices" + } + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesKibanaDependencies", + "type": "Interface", + "tags": [], + "label": "UserProfilesKibanaDependencies", + "description": [], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesKibanaDependencies.core", + "type": "Object", + "tags": [], + "label": "core", + "description": [], + "signature": [ + "{ userProfile: { bulkGet: (params: ", + { + "pluginId": "@kbn/core-user-profile-browser", + "scope": "common", + "docId": "kibKbnCoreUserProfileBrowserPluginApi", + "section": "def-common.UserProfileBulkGetParams", + "text": "UserProfileBulkGetParams" + }, + ") => Promise<", + { + "pluginId": "@kbn/core-user-profile-common", + "scope": "common", + "docId": "kibKbnCoreUserProfileCommonPluginApi", + "section": "def-common.UserProfile", + "text": "UserProfile" + }, + "[]>; }; }" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesServices", + "type": "Interface", + "tags": [], + "label": "UserProfilesServices", + "description": [], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesServices.bulkGetUserProfiles", + "type": "Function", + "tags": [], + "label": "bulkGetUserProfiles", + "description": [], + "signature": [ + "(uids: string[]) => Promise<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfile", + "text": "UserProfile" + }, + "<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfileData", + "text": "UserProfileData" + }, + ">[]>" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesServices.bulkGetUserProfiles.$1", + "type": "Array", + "tags": [], + "label": "uids", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesServices.getUserProfile", + "type": "Function", + "tags": [], + "label": "getUserProfile", + "description": [], + "signature": [ + "(uid: string) => Promise<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfile", + "text": "UserProfile" + }, + "<", + { + "pluginId": "@kbn/user-profile-components", + "scope": "common", + "docId": "kibKbnUserProfileComponentsPluginApi", + "section": "def-common.UserProfileData", + "text": "UserProfileData" + }, + ">>" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/content-management-user-profiles", + "id": "def-common.UserProfilesServices.getUserProfile.$1", + "type": "string", + "tags": [], + "label": "uid", + "description": [], + "signature": [ + "string" + ], + "path": "packages/content-management/user_profiles/src/services.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_content_management_user_profiles.mdx b/api_docs/kbn_content_management_user_profiles.mdx new file mode 100644 index 0000000000000..8c7fdd49f0c66 --- /dev/null +++ b/api_docs/kbn_content_management_user_profiles.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnContentManagementUserProfilesPluginApi +slug: /kibana-dev-docs/api/kbn-content-management-user-profiles +title: "@kbn/content-management-user-profiles" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/content-management-user-profiles plugin +date: 2024-06-19 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-user-profiles'] +--- +import kbnContentManagementUserProfilesObj from './kbn_content_management_user_profiles.devdocs.json'; + + + +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 30 | 0 | 30 | 0 | + +## Common + +### Functions + + +### Interfaces + + diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index 95d831172342a..5e36fe54ede76 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.devdocs.json b/api_docs/kbn_core_analytics_browser.devdocs.json index 1f9e8beb3c160..7f19ef23a3e2d 100644 --- a/api_docs/kbn_core_analytics_browser.devdocs.json +++ b/api_docs/kbn_core_analytics_browser.devdocs.json @@ -20,36 +20,2867 @@ "classes": [], "functions": [], "interfaces": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AnalyticsClientInitContext", + "type": "Interface", + "tags": [], + "label": "AnalyticsClientInitContext", + "description": [ + "\nGeneral settings of the analytics client" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AnalyticsClientInitContext.isDev", + "type": "boolean", + "tags": [], + "label": "isDev", + "description": [ + "\nBoolean indicating if it's running in developer mode." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AnalyticsClientInitContext.sendTo", + "type": "CompoundType", + "tags": [], + "label": "sendTo", + "description": [ + "\nSpecify if the shippers should send their data to the production or staging environments." + ], + "signature": [ + "\"production\" | \"staging\"" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AnalyticsClientInitContext.logger", + "type": "Object", + "tags": [], + "label": "logger", + "description": [ + "\nApplication-provided logger." + ], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ContextProviderOpts", + "type": "Interface", + "tags": [], + "label": "ContextProviderOpts", + "description": [ + "\nDefinition of a context provider" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ContextProviderOpts.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nThe name of the provider." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ContextProviderOpts.context$", + "type": "Object", + "tags": [], + "label": "context$", + "description": [ + "\nObservable that emits the custom context." + ], + "signature": [ + "Observable", + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ContextProviderOpts.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [ + "\nSchema declaring and documenting the expected output in the context$\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.Event", + "type": "Interface", + "tags": [], + "label": "Event", + "description": [ + "\nDefinition of the full event structure" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.Event.timestamp", + "type": "string", + "tags": [], + "label": "timestamp", + "description": [ + "\nThe time the event was generated in ISO format." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.Event.event_type", + "type": "string", + "tags": [], + "label": "event_type", + "description": [ + "\nThe event type." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.Event.properties", + "type": "Uncategorized", + "tags": [], + "label": "properties", + "description": [ + "\nThe specific properties of the event type." + ], + "signature": [ + "Properties" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.Event.context", + "type": "Object", + "tags": [], + "label": "context", + "description": [ + "\nThe {@link EventContext} enriched during the processing pipeline." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext", + "type": "Interface", + "tags": [], + "label": "EventContext", + "description": [ + "\nDefinition of the context that can be appended to the events through the {@link IAnalyticsClient.registerContextProvider}." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.cluster_uuid", + "type": "string", + "tags": [], + "label": "cluster_uuid", + "description": [ + "\nThe UUID of the cluster" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.cluster_name", + "type": "string", + "tags": [], + "label": "cluster_name", + "description": [ + "\nThe name of the cluster." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.license_id", + "type": "string", + "tags": [], + "label": "license_id", + "description": [ + "\nThe license ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.userId", + "type": "string", + "tags": [], + "label": "userId", + "description": [ + "\nThe unique user ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.cloudId", + "type": "string", + "tags": [], + "label": "cloudId", + "description": [ + "\nThe Cloud ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.isElasticCloudUser", + "type": "CompoundType", + "tags": [], + "label": "isElasticCloudUser", + "description": [ + "\n`true` if the user is logged in via the Elastic Cloud authentication provider." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.version", + "type": "string", + "tags": [], + "label": "version", + "description": [ + "\nThe product's version." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.pageName", + "type": "string", + "tags": [], + "label": "pageName", + "description": [ + "\nThe name of the current page." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.applicationId", + "type": "string", + "tags": [], + "label": "applicationId", + "description": [ + "\nThe current application ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.entityId", + "type": "string", + "tags": [], + "label": "entityId", + "description": [ + "\nThe current entity ID (dashboard ID, visualization ID, etc.)." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventContext.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[key: string]: unknown", + "description": [ + "\nAdditional keys are allowed." + ], + "signature": [ + "[key: string]: unknown" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventTypeOpts", + "type": "Interface", + "tags": [], + "label": "EventTypeOpts", + "description": [ + "\nDefinition of an Event Type." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventTypeOpts.eventType", + "type": "string", + "tags": [], + "label": "eventType", + "description": [ + "\nThe event type's unique name." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventTypeOpts.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [ + "\nSchema declaring and documenting the expected structure of this event type.\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient", + "type": "Interface", + "tags": [], + "label": "IAnalyticsClient", + "description": [ + "\nAnalytics client's public APIs" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.reportEvent", + "type": "Function", + "tags": [ + "track-adoption" + ], + "label": "reportEvent", + "description": [ + "\nReports a telemetry event." + ], + "signature": [ + "(eventType: string, eventData: EventTypeData) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "@kbn/core-notifications-browser-internal", + "path": "packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_reporter.ts" + }, + { + "plugin": "@kbn/core-notifications-browser-internal", + "path": "packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_reporter.ts" + }, + { + "plugin": "@kbn/ebt-tools", + "path": "packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-server-internal", + "path": "packages/core/root/core-root-server-internal/src/events/kibana_started.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/types.ts" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/analytics_service.ts" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/server/utils/recall/recall_and_score.ts" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" + }, + { + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + }, + { + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/usage/event_tracker.ts" + }, + { + "plugin": "searchPlayground", + "path": "x-pack/plugins/search_playground/server/routes.ts" + }, + { + "plugin": "securitySolutionServerless", + "path": "x-pack/plugins/security_solution_serverless/server/task_manager/nlp_cleanup_task/nlp_cleanup_task.ts" + }, + { + "plugin": "securitySolutionServerless", + "path": "x-pack/plugins/security_solution_serverless/server/task_manager/nlp_cleanup_task/nlp_cleanup_task.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "observabilityLogsExplorer", + "path": "x-pack/plugins/observability_solution/observability_logs_explorer/public/state_machines/observability_logs_explorer/src/telemetry_events.ts" + }, + { + "plugin": "observabilityOnboarding", + "path": "x-pack/plugins/observability_solution/observability_onboarding/public/hooks/use_flow_progress_telemetry.ts" + }, + { + "plugin": "observabilityOnboarding", + "path": "x-pack/plugins/observability_solution/observability_onboarding/public/application/app.tsx" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/analytics.stub.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.reportEvent.$1", + "type": "string", + "tags": [], + "label": "eventType", + "description": [ + "The event type registered via the `registerEventType` API." + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.reportEvent.$2", + "type": "Uncategorized", + "tags": [], + "label": "eventData", + "description": [ + "The properties matching the schema declared in the `registerEventType` API." + ], + "signature": [ + "EventTypeData" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerEventType", + "type": "Function", + "tags": [], + "label": "registerEventType", + "description": [ + "\nRegisters the event type that will be emitted via the reportEvent API." + ], + "signature": [ + "(eventTypeOps: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerEventType.$1", + "type": "Object", + "tags": [], + "label": "eventTypeOps", + "description": [ + "The definition of the event type {@link EventTypeOpts }." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerShipper", + "type": "Function", + "tags": [], + "label": "registerShipper", + "description": [ + "\nSet up the shipper that will be used to report the telemetry events." + ], + "signature": [ + "(Shipper: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + ", shipperConfig: ShipperConfig, opts?: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.RegisterShipperOpts", + "text": "RegisterShipperOpts" + }, + " | undefined) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerShipper.$1", + "type": "Object", + "tags": [], + "label": "Shipper", + "description": [ + "The {@link IShipper } class to instantiate the shipper." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerShipper.$2", + "type": "Uncategorized", + "tags": [], + "label": "shipperConfig", + "description": [ + "The config specific to the Shipper to instantiate." + ], + "signature": [ + "ShipperConfig" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerShipper.$3", + "type": "Object", + "tags": [], + "label": "opts", + "description": [ + "Additional options to register the shipper {@link RegisterShipperOpts }." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.RegisterShipperOpts", + "text": "RegisterShipperOpts" + }, + " | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nUsed to control the user's consent to report the data.\nIn the advanced mode, it allows to \"cherry-pick\" which events and shippers are enabled/disabled." + ], + "signature": [ + "(optInConfig: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfig", + "text": "OptInConfig" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.optIn.$1", + "type": "Object", + "tags": [], + "label": "optInConfig", + "description": [ + "{@link OptInConfig }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfig", + "text": "OptInConfig" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerContextProvider", + "type": "Function", + "tags": [ + "track-adoption" + ], + "label": "registerContextProvider", + "description": [ + "\nRegisters the context provider to enrich any reported events." + ], + "signature": [ + "(contextProviderOpts: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-elasticsearch-server-internal", + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-environment-server-internal", + "path": "packages/core/environment/core-environment-server-internal/src/environment_service.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts" + }, + { + "plugin": "licensing", + "path": "x-pack/plugins/licensing/common/register_analytics_context_provider.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/plugin.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/plugin.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.test.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-elasticsearch-server-internal", + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.registerContextProvider.$1", + "type": "Object", + "tags": [], + "label": "contextProviderOpts", + "description": [ + "{@link ContextProviderOpts }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.removeContextProvider", + "type": "Function", + "tags": [], + "label": "removeContextProvider", + "description": [ + "\nRemoves the context provider and stop enriching the events from its context." + ], + "signature": [ + "(contextProviderName: string) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.removeContextProvider.$1", + "type": "string", + "tags": [], + "label": "contextProviderName", + "description": [ + "The name of the context provider to remove." + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "\nObservable to emit the stats of the processed events." + ], + "signature": [ + "Observable", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + ">" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nForces all shippers to send all their enqueued events and fulfills the returned promise." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IAnalyticsClient.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nStops the client. Flushing any pending events in the process." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper", + "type": "Interface", + "tags": [], + "label": "IShipper", + "description": [ + "\nBasic structure of a Shipper" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.reportEvents", + "type": "Function", + "tags": [], + "label": "reportEvents", + "description": [ + "\nAdapts and ships the event to the persisting/analytics solution." + ], + "signature": [ + "(events: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]) => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.reportEvents.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [ + "batched events {@link Event }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nStops/restarts the shipping mechanism based on the value of isOptedIn" + ], + "signature": [ + "(isOptedIn: boolean) => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.optIn.$1", + "type": "boolean", + "tags": [], + "label": "isOptedIn", + "description": [ + "`true` for resume sending events. `false` to stop." + ], + "signature": [ + "boolean" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.extendContext", + "type": "Function", + "tags": [], + "label": "extendContext", + "description": [ + "\nPerform any necessary calls to the persisting/analytics solution to set the event's context." + ], + "signature": [ + "((newContext: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + }, + ") => void) | undefined" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.extendContext.$1", + "type": "Object", + "tags": [], + "label": "newContext", + "description": [ + "The full new context to set {@link EventContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "\nObservable to emit the stats of the processed events." + ], + "signature": [ + "Observable", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + "> | undefined" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nSends all the enqueued events and fulfills the returned promise." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.IShipper.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nShutdown the shipper." + ], + "signature": [ + "() => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-analytics-browser", "id": "def-common.KbnAnalyticsWindowApi", "type": "Interface", "tags": [], - "label": "KbnAnalyticsWindowApi", + "label": "KbnAnalyticsWindowApi", + "description": [ + "\nAPI exposed through `window.__kbnAnalytics`" + ], + "path": "packages/core/analytics/core-analytics-browser/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.KbnAnalyticsWindowApi.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nReturns a promise that resolves when all the events in the queue have been sent." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/core/analytics/core-analytics-browser/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.OptInConfig", + "type": "Interface", + "tags": [], + "label": "OptInConfig", + "description": [ + "\nOptions for the optIn API" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.OptInConfig.global", + "type": "Object", + "tags": [], + "label": "global", + "description": [ + "\nControls the global enabled/disabled behaviour of the client and shippers." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfigPerType", + "text": "OptInConfigPerType" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.OptInConfig.event_types", + "type": "Object", + "tags": [], + "label": "event_types", + "description": [ + "\nControls if an event type should be disabled for a specific type of shipper." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.OptInConfigPerType", + "type": "Interface", + "tags": [], + "label": "OptInConfigPerType", + "description": [ + "\nSets whether a type of event is enabled/disabled globally or per shipper." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.OptInConfigPerType.enabled", + "type": "boolean", + "tags": [], + "label": "enabled", + "description": [ + "\nThe event type is globally enabled." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.OptInConfigPerType.shippers", + "type": "Object", + "tags": [], + "label": "shippers", + "description": [ + "\nControls if an event type should be disabled for a specific type of shipper." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.RegisterShipperOpts", + "type": "Interface", + "tags": [], + "label": "RegisterShipperOpts", + "description": [ + "\nOptional options to register a shipper" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaArray", + "type": "Interface", + "tags": [], + "label": "SchemaArray", + "description": [ + "\nSchema to represent an array" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaArray.type", + "type": "string", + "tags": [], + "label": "type", + "description": [ + "The type must be an array" + ], + "signature": [ + "\"array\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaArray.items", + "type": "CompoundType", + "tags": [], + "label": "items", + "description": [ + "The schema of the items in the array is defined in the `items` property" + ], + "signature": [ + "{ type: \"pass_through\"; _meta: { description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "; } | (unknown extends Value ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends (infer U)[] | readonly (infer U)[] ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " : NonNullable extends Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends object ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + ")" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaChildValue", + "type": "Interface", + "tags": [], + "label": "SchemaChildValue", + "description": [ + "\nSchema to define a primitive value" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaChildValue.type", + "type": "Uncategorized", + "tags": [], + "label": "type", + "description": [ + "The type of the value" + ], + "signature": [ + "NonNullable extends string | Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaStringTypes", + "text": "AllowedSchemaStringTypes" + }, + " : NonNullable extends number ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaNumberTypes", + "text": "AllowedSchemaNumberTypes" + }, + " : NonNullable extends boolean ? \"boolean\" : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaTypes", + "text": "AllowedSchemaTypes" + } + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaChildValue._meta", + "type": "CompoundType", + "tags": [], + "label": "_meta", + "description": [ + "Meta properties of the value: description and is optional" + ], + "signature": [ + "{ description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaMeta", + "type": "Interface", + "tags": [], + "label": "SchemaMeta", + "description": [ + "\nSchema meta with optional description" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaMeta._meta", + "type": "CompoundType", + "tags": [], + "label": "_meta", + "description": [ + "Meta properties of the pass through: description and is optional" + ], + "signature": [ + "({ description?: string | undefined; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + ") | undefined" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaObject", + "type": "Interface", + "tags": [], + "label": "SchemaObject", + "description": [ + "\nSchema to represent an object" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaObject.properties", + "type": "Object", + "tags": [], + "label": "properties", + "description": [ + "\nThe schemas of the keys of the object are defined in the `properties` object." + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ShipperClassConstructor", + "type": "Interface", + "tags": [], + "label": "ShipperClassConstructor", "description": [ - "\nAPI exposed through `window.__kbnAnalytics`" + "\nConstructor of a {@link IShipper}" ], - "path": "packages/core/analytics/core-analytics-browser/src/types.ts", + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/core-analytics-browser", - "id": "def-common.KbnAnalyticsWindowApi.flush", + "id": "def-common.ShipperClassConstructor.shipperName", + "type": "string", + "tags": [], + "label": "shipperName", + "description": [ + "\nThe shipper's unique name" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ShipperClassConstructor.new", "type": "Function", "tags": [], - "label": "flush", + "label": "new", "description": [ - "\nReturns a promise that resolves when all the events in the queue have been sent." + "\nThe constructor" ], "signature": [ - "() => Promise" + "any" ], - "path": "packages/core/analytics/core-analytics-browser/src/types.ts", + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", "deprecated": false, "trackAdoption": false, - "returnComment": [], - "children": [] + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ShipperClassConstructor.new.$1", + "type": "Uncategorized", + "tags": [], + "label": "config", + "description": [ + "The shipper's custom config" + ], + "signature": [ + "Config" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ShipperClassConstructor.new.$2", + "type": "Object", + "tags": [], + "label": "initContext", + "description": [ + "Common context {@link AnalyticsClientInitContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AnalyticsClientInitContext", + "text": "AnalyticsClientInitContext" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounter", + "type": "Interface", + "tags": [], + "label": "TelemetryCounter", + "description": [ + "\nShape of the events emitted by the telemetryCounter$ observable" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounter.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [ + "\n{@link TelemetryCounterType}" + ], + "signature": [ + "\"succeeded\" | \"failed\" | \"enqueued\" | \"sent_to_shipper\" | \"dropped\"" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounter.source", + "type": "string", + "tags": [], + "label": "source", + "description": [ + "\nWho emitted the event? It can be \"client\" or the name of the shipper." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounter.event_type", + "type": "string", + "tags": [], + "label": "event_type", + "description": [ + "\nThe event type the success/failure/drop event refers to." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounter.code", + "type": "string", + "tags": [], + "label": "code", + "description": [ + "\nCode to provide additional information about the success or failure. Examples are 200/400/504/ValidationError/UnknownError" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounter.count", + "type": "number", + "tags": [], + "label": "count", + "description": [ + "\nThe number of events that this counter refers to." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -57,6 +2888,74 @@ ], "enums": [], "misc": [ + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AllowedSchemaBooleanTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaBooleanTypes", + "description": [ + "Types matching boolean values" + ], + "signature": [ + "\"boolean\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AllowedSchemaNumberTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaNumberTypes", + "description": [ + "Types matching number values" + ], + "signature": [ + "\"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AllowedSchemaStringTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaStringTypes", + "description": [ + "Types matching string values" + ], + "signature": [ + "\"keyword\" | \"text\" | \"date\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.AllowedSchemaTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaTypes", + "description": [ + "\nPossible type values in the schema" + ], + "signature": [ + "\"boolean\" | \"keyword\" | \"text\" | \"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-analytics-browser", "id": "def-common.AnalyticsServiceSetup", @@ -69,9 +2968,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -79,49 +2978,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, @@ -144,9 +3043,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -154,9 +3053,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, @@ -166,6 +3065,237 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ContextProviderName", + "type": "Type", + "tags": [], + "label": "ContextProviderName", + "description": [ + "\nContextProviderName used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.EventType", + "type": "Type", + "tags": [], + "label": "EventType", + "description": [ + "\nEvent Type used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.PossibleSchemaTypes", + "type": "Type", + "tags": [], + "label": "PossibleSchemaTypes", + "description": [ + "\nHelper to ensure the declared types match the schema types" + ], + "signature": [ + "Value extends string | Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaStringTypes", + "text": "AllowedSchemaStringTypes" + }, + " : Value extends number ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaNumberTypes", + "text": "AllowedSchemaNumberTypes" + }, + " : Value extends boolean ? \"boolean\" : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaTypes", + "text": "AllowedSchemaTypes" + } + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.RootSchema", + "type": "Type", + "tags": [], + "label": "RootSchema", + "description": [ + "\nSchema definition to match the structure of the properties provided.\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaMetaOptional", + "type": "Type", + "tags": [], + "label": "SchemaMetaOptional", + "description": [ + "\nEnforces { optional: true } if the value can be undefined" + ], + "signature": [ + "unknown extends Value ? { optional?: boolean | undefined; } : undefined extends Value ? { optional: true; } : { optional?: false | undefined; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.SchemaValue", + "type": "Type", + "tags": [], + "label": "SchemaValue", + "description": [ + "\nType that defines all the possible values that the Schema accepts.\nThese types definitions are helping to identify earlier the possible missing `properties` nesting when\nmanually defining the schemas." + ], + "signature": [ + "{ type: \"pass_through\"; _meta: { description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "; } | (unknown extends Value ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends (infer U)[] | readonly (infer U)[] ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " : NonNullable extends Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends object ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + ")" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.ShipperName", + "type": "Type", + "tags": [], + "label": "ShipperName", + "description": [ + "\nShipper Name used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-browser", + "id": "def-common.TelemetryCounterType", + "type": "Type", + "tags": [], + "label": "TelemetryCounterType", + "description": [ + "\nIndicates if the event contains data about succeeded, failed or dropped events:\n- enqueued: The event was accepted and will be sent to the shippers when they become available (and opt-in === true).\n- sent_to_shipper: The event was sent to at least one shipper.\n- succeeded: The event was successfully sent by the shipper.\n- failed: There was an error when processing/shipping the event. Refer to the Telemetry Counter's code for the reason.\n- dropped: The event was dropped from the queue. Refer to the Telemetry Counter's code for the reason." + ], + "signature": [ + "\"succeeded\" | \"failed\" | \"enqueued\" | \"sent_to_shipper\" | \"dropped\"" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [] diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 5e8fb7e681138..c8ff98d0fd1d8 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.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 | |-------------------|-----------|------------------------|-----------------| -| 4 | 0 | 0 | 0 | +| 101 | 0 | 0 | 0 | ## Common diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 79058a9a104e2..a8a42992594af 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: 2024-06-18 +date: 2024-06-19 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 6c6b2b592bb48..f6911a5bcdb2b 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_core_analytics_server.devdocs.json index 9f116d542418f..5c4760eb2c883 100644 --- a/api_docs/kbn_core_analytics_server.devdocs.json +++ b/api_docs/kbn_core_analytics_server.devdocs.json @@ -19,9 +19,2909 @@ "common": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AnalyticsClientInitContext", + "type": "Interface", + "tags": [], + "label": "AnalyticsClientInitContext", + "description": [ + "\nGeneral settings of the analytics client" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AnalyticsClientInitContext.isDev", + "type": "boolean", + "tags": [], + "label": "isDev", + "description": [ + "\nBoolean indicating if it's running in developer mode." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AnalyticsClientInitContext.sendTo", + "type": "CompoundType", + "tags": [], + "label": "sendTo", + "description": [ + "\nSpecify if the shippers should send their data to the production or staging environments." + ], + "signature": [ + "\"production\" | \"staging\"" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AnalyticsClientInitContext.logger", + "type": "Object", + "tags": [], + "label": "logger", + "description": [ + "\nApplication-provided logger." + ], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ContextProviderOpts", + "type": "Interface", + "tags": [], + "label": "ContextProviderOpts", + "description": [ + "\nDefinition of a context provider" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ContextProviderOpts.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nThe name of the provider." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ContextProviderOpts.context$", + "type": "Object", + "tags": [], + "label": "context$", + "description": [ + "\nObservable that emits the custom context." + ], + "signature": [ + "Observable", + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ContextProviderOpts.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [ + "\nSchema declaring and documenting the expected output in the context$\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.Event", + "type": "Interface", + "tags": [], + "label": "Event", + "description": [ + "\nDefinition of the full event structure" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.Event.timestamp", + "type": "string", + "tags": [], + "label": "timestamp", + "description": [ + "\nThe time the event was generated in ISO format." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.Event.event_type", + "type": "string", + "tags": [], + "label": "event_type", + "description": [ + "\nThe event type." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.Event.properties", + "type": "Uncategorized", + "tags": [], + "label": "properties", + "description": [ + "\nThe specific properties of the event type." + ], + "signature": [ + "Properties" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.Event.context", + "type": "Object", + "tags": [], + "label": "context", + "description": [ + "\nThe {@link EventContext} enriched during the processing pipeline." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext", + "type": "Interface", + "tags": [], + "label": "EventContext", + "description": [ + "\nDefinition of the context that can be appended to the events through the {@link IAnalyticsClient.registerContextProvider}." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.cluster_uuid", + "type": "string", + "tags": [], + "label": "cluster_uuid", + "description": [ + "\nThe UUID of the cluster" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.cluster_name", + "type": "string", + "tags": [], + "label": "cluster_name", + "description": [ + "\nThe name of the cluster." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.license_id", + "type": "string", + "tags": [], + "label": "license_id", + "description": [ + "\nThe license ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.userId", + "type": "string", + "tags": [], + "label": "userId", + "description": [ + "\nThe unique user ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.cloudId", + "type": "string", + "tags": [], + "label": "cloudId", + "description": [ + "\nThe Cloud ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.isElasticCloudUser", + "type": "CompoundType", + "tags": [], + "label": "isElasticCloudUser", + "description": [ + "\n`true` if the user is logged in via the Elastic Cloud authentication provider." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.version", + "type": "string", + "tags": [], + "label": "version", + "description": [ + "\nThe product's version." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.pageName", + "type": "string", + "tags": [], + "label": "pageName", + "description": [ + "\nThe name of the current page." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.applicationId", + "type": "string", + "tags": [], + "label": "applicationId", + "description": [ + "\nThe current application ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.entityId", + "type": "string", + "tags": [], + "label": "entityId", + "description": [ + "\nThe current entity ID (dashboard ID, visualization ID, etc.)." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventContext.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[key: string]: unknown", + "description": [ + "\nAdditional keys are allowed." + ], + "signature": [ + "[key: string]: unknown" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventTypeOpts", + "type": "Interface", + "tags": [], + "label": "EventTypeOpts", + "description": [ + "\nDefinition of an Event Type." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventTypeOpts.eventType", + "type": "string", + "tags": [], + "label": "eventType", + "description": [ + "\nThe event type's unique name." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventTypeOpts.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [ + "\nSchema declaring and documenting the expected structure of this event type.\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient", + "type": "Interface", + "tags": [], + "label": "IAnalyticsClient", + "description": [ + "\nAnalytics client's public APIs" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.reportEvent", + "type": "Function", + "tags": [ + "track-adoption" + ], + "label": "reportEvent", + "description": [ + "\nReports a telemetry event." + ], + "signature": [ + "(eventType: string, eventData: EventTypeData) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "@kbn/core-notifications-browser-internal", + "path": "packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_reporter.ts" + }, + { + "plugin": "@kbn/core-notifications-browser-internal", + "path": "packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_reporter.ts" + }, + { + "plugin": "@kbn/ebt-tools", + "path": "packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-server-internal", + "path": "packages/core/root/core-root-server-internal/src/events/kibana_started.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/types.ts" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/analytics_service.ts" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/server/utils/recall/recall_and_score.ts" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" + }, + { + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + }, + { + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/usage/event_tracker.ts" + }, + { + "plugin": "searchPlayground", + "path": "x-pack/plugins/search_playground/server/routes.ts" + }, + { + "plugin": "securitySolutionServerless", + "path": "x-pack/plugins/security_solution_serverless/server/task_manager/nlp_cleanup_task/nlp_cleanup_task.ts" + }, + { + "plugin": "securitySolutionServerless", + "path": "x-pack/plugins/security_solution_serverless/server/task_manager/nlp_cleanup_task/nlp_cleanup_task.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "observabilityLogsExplorer", + "path": "x-pack/plugins/observability_solution/observability_logs_explorer/public/state_machines/observability_logs_explorer/src/telemetry_events.ts" + }, + { + "plugin": "observabilityOnboarding", + "path": "x-pack/plugins/observability_solution/observability_onboarding/public/hooks/use_flow_progress_telemetry.ts" + }, + { + "plugin": "observabilityOnboarding", + "path": "x-pack/plugins/observability_solution/observability_onboarding/public/application/app.tsx" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/analytics.stub.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.reportEvent.$1", + "type": "string", + "tags": [], + "label": "eventType", + "description": [ + "The event type registered via the `registerEventType` API." + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.reportEvent.$2", + "type": "Uncategorized", + "tags": [], + "label": "eventData", + "description": [ + "The properties matching the schema declared in the `registerEventType` API." + ], + "signature": [ + "EventTypeData" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerEventType", + "type": "Function", + "tags": [], + "label": "registerEventType", + "description": [ + "\nRegisters the event type that will be emitted via the reportEvent API." + ], + "signature": [ + "(eventTypeOps: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerEventType.$1", + "type": "Object", + "tags": [], + "label": "eventTypeOps", + "description": [ + "The definition of the event type {@link EventTypeOpts }." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerShipper", + "type": "Function", + "tags": [], + "label": "registerShipper", + "description": [ + "\nSet up the shipper that will be used to report the telemetry events." + ], + "signature": [ + "(Shipper: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + ", shipperConfig: ShipperConfig, opts?: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.RegisterShipperOpts", + "text": "RegisterShipperOpts" + }, + " | undefined) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerShipper.$1", + "type": "Object", + "tags": [], + "label": "Shipper", + "description": [ + "The {@link IShipper } class to instantiate the shipper." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerShipper.$2", + "type": "Uncategorized", + "tags": [], + "label": "shipperConfig", + "description": [ + "The config specific to the Shipper to instantiate." + ], + "signature": [ + "ShipperConfig" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerShipper.$3", + "type": "Object", + "tags": [], + "label": "opts", + "description": [ + "Additional options to register the shipper {@link RegisterShipperOpts }." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.RegisterShipperOpts", + "text": "RegisterShipperOpts" + }, + " | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nUsed to control the user's consent to report the data.\nIn the advanced mode, it allows to \"cherry-pick\" which events and shippers are enabled/disabled." + ], + "signature": [ + "(optInConfig: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfig", + "text": "OptInConfig" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.optIn.$1", + "type": "Object", + "tags": [], + "label": "optInConfig", + "description": [ + "{@link OptInConfig }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfig", + "text": "OptInConfig" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerContextProvider", + "type": "Function", + "tags": [ + "track-adoption" + ], + "label": "registerContextProvider", + "description": [ + "\nRegisters the context provider to enrich any reported events." + ], + "signature": [ + "(contextProviderOpts: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-elasticsearch-server-internal", + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-environment-server-internal", + "path": "packages/core/environment/core-environment-server-internal/src/environment_service.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts" + }, + { + "plugin": "licensing", + "path": "x-pack/plugins/licensing/common/register_analytics_context_provider.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/plugin.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/plugin.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/analytics_client.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.test.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-elasticsearch-server-internal", + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/ebt", + "path": "packages/analytics/ebt/client/src/analytics_client/mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.registerContextProvider.$1", + "type": "Object", + "tags": [], + "label": "contextProviderOpts", + "description": [ + "{@link ContextProviderOpts }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.removeContextProvider", + "type": "Function", + "tags": [], + "label": "removeContextProvider", + "description": [ + "\nRemoves the context provider and stop enriching the events from its context." + ], + "signature": [ + "(contextProviderName: string) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.removeContextProvider.$1", + "type": "string", + "tags": [], + "label": "contextProviderName", + "description": [ + "The name of the context provider to remove." + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "\nObservable to emit the stats of the processed events." + ], + "signature": [ + "Observable", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + ">" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nForces all shippers to send all their enqueued events and fulfills the returned promise." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IAnalyticsClient.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nStops the client. Flushing any pending events in the process." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper", + "type": "Interface", + "tags": [], + "label": "IShipper", + "description": [ + "\nBasic structure of a Shipper" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.reportEvents", + "type": "Function", + "tags": [], + "label": "reportEvents", + "description": [ + "\nAdapts and ships the event to the persisting/analytics solution." + ], + "signature": [ + "(events: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]) => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.reportEvents.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [ + "batched events {@link Event }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nStops/restarts the shipping mechanism based on the value of isOptedIn" + ], + "signature": [ + "(isOptedIn: boolean) => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.optIn.$1", + "type": "boolean", + "tags": [], + "label": "isOptedIn", + "description": [ + "`true` for resume sending events. `false` to stop." + ], + "signature": [ + "boolean" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.extendContext", + "type": "Function", + "tags": [], + "label": "extendContext", + "description": [ + "\nPerform any necessary calls to the persisting/analytics solution to set the event's context." + ], + "signature": [ + "((newContext: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + }, + ") => void) | undefined" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.extendContext.$1", + "type": "Object", + "tags": [], + "label": "newContext", + "description": [ + "The full new context to set {@link EventContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "\nObservable to emit the stats of the processed events." + ], + "signature": [ + "Observable", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + "> | undefined" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nSends all the enqueued events and fulfills the returned promise." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.IShipper.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nShutdown the shipper." + ], + "signature": [ + "() => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.OptInConfig", + "type": "Interface", + "tags": [], + "label": "OptInConfig", + "description": [ + "\nOptions for the optIn API" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.OptInConfig.global", + "type": "Object", + "tags": [], + "label": "global", + "description": [ + "\nControls the global enabled/disabled behaviour of the client and shippers." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfigPerType", + "text": "OptInConfigPerType" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.OptInConfig.event_types", + "type": "Object", + "tags": [], + "label": "event_types", + "description": [ + "\nControls if an event type should be disabled for a specific type of shipper." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.OptInConfigPerType", + "type": "Interface", + "tags": [], + "label": "OptInConfigPerType", + "description": [ + "\nSets whether a type of event is enabled/disabled globally or per shipper." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.OptInConfigPerType.enabled", + "type": "boolean", + "tags": [], + "label": "enabled", + "description": [ + "\nThe event type is globally enabled." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.OptInConfigPerType.shippers", + "type": "Object", + "tags": [], + "label": "shippers", + "description": [ + "\nControls if an event type should be disabled for a specific type of shipper." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.RegisterShipperOpts", + "type": "Interface", + "tags": [], + "label": "RegisterShipperOpts", + "description": [ + "\nOptional options to register a shipper" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaArray", + "type": "Interface", + "tags": [], + "label": "SchemaArray", + "description": [ + "\nSchema to represent an array" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaArray.type", + "type": "string", + "tags": [], + "label": "type", + "description": [ + "The type must be an array" + ], + "signature": [ + "\"array\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaArray.items", + "type": "CompoundType", + "tags": [], + "label": "items", + "description": [ + "The schema of the items in the array is defined in the `items` property" + ], + "signature": [ + "{ type: \"pass_through\"; _meta: { description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "; } | (unknown extends Value ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends (infer U)[] | readonly (infer U)[] ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " : NonNullable extends Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends object ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + ")" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaChildValue", + "type": "Interface", + "tags": [], + "label": "SchemaChildValue", + "description": [ + "\nSchema to define a primitive value" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaChildValue.type", + "type": "Uncategorized", + "tags": [], + "label": "type", + "description": [ + "The type of the value" + ], + "signature": [ + "NonNullable extends string | Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaStringTypes", + "text": "AllowedSchemaStringTypes" + }, + " : NonNullable extends number ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaNumberTypes", + "text": "AllowedSchemaNumberTypes" + }, + " : NonNullable extends boolean ? \"boolean\" : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaTypes", + "text": "AllowedSchemaTypes" + } + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaChildValue._meta", + "type": "CompoundType", + "tags": [], + "label": "_meta", + "description": [ + "Meta properties of the value: description and is optional" + ], + "signature": [ + "{ description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaMeta", + "type": "Interface", + "tags": [], + "label": "SchemaMeta", + "description": [ + "\nSchema meta with optional description" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaMeta._meta", + "type": "CompoundType", + "tags": [], + "label": "_meta", + "description": [ + "Meta properties of the pass through: description and is optional" + ], + "signature": [ + "({ description?: string | undefined; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + ") | undefined" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaObject", + "type": "Interface", + "tags": [], + "label": "SchemaObject", + "description": [ + "\nSchema to represent an object" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaObject.properties", + "type": "Object", + "tags": [], + "label": "properties", + "description": [ + "\nThe schemas of the keys of the object are defined in the `properties` object." + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ShipperClassConstructor", + "type": "Interface", + "tags": [], + "label": "ShipperClassConstructor", + "description": [ + "\nConstructor of a {@link IShipper}" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ShipperClassConstructor.shipperName", + "type": "string", + "tags": [], + "label": "shipperName", + "description": [ + "\nThe shipper's unique name" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ShipperClassConstructor.new", + "type": "Function", + "tags": [], + "label": "new", + "description": [ + "\nThe constructor" + ], + "signature": [ + "any" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ShipperClassConstructor.new.$1", + "type": "Uncategorized", + "tags": [], + "label": "config", + "description": [ + "The shipper's custom config" + ], + "signature": [ + "Config" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ShipperClassConstructor.new.$2", + "type": "Object", + "tags": [], + "label": "initContext", + "description": [ + "Common context {@link AnalyticsClientInitContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AnalyticsClientInitContext", + "text": "AnalyticsClientInitContext" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounter", + "type": "Interface", + "tags": [], + "label": "TelemetryCounter", + "description": [ + "\nShape of the events emitted by the telemetryCounter$ observable" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounter.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [ + "\n{@link TelemetryCounterType}" + ], + "signature": [ + "\"succeeded\" | \"failed\" | \"enqueued\" | \"sent_to_shipper\" | \"dropped\"" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounter.source", + "type": "string", + "tags": [], + "label": "source", + "description": [ + "\nWho emitted the event? It can be \"client\" or the name of the shipper." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounter.event_type", + "type": "string", + "tags": [], + "label": "event_type", + "description": [ + "\nThe event type the success/failure/drop event refers to." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounter.code", + "type": "string", + "tags": [], + "label": "code", + "description": [ + "\nCode to provide additional information about the success or failure. Examples are 200/400/504/ValidationError/UnknownError" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounter.count", + "type": "number", + "tags": [], + "label": "count", + "description": [ + "\nThe number of events that this counter refers to." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [ + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AllowedSchemaBooleanTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaBooleanTypes", + "description": [ + "Types matching boolean values" + ], + "signature": [ + "\"boolean\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AllowedSchemaNumberTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaNumberTypes", + "description": [ + "Types matching number values" + ], + "signature": [ + "\"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AllowedSchemaStringTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaStringTypes", + "description": [ + "Types matching string values" + ], + "signature": [ + "\"keyword\" | \"text\" | \"date\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.AllowedSchemaTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaTypes", + "description": [ + "\nPossible type values in the schema" + ], + "signature": [ + "\"boolean\" | \"keyword\" | \"text\" | \"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-analytics-server", "id": "def-common.AnalyticsServicePreboot", @@ -34,9 +2934,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -44,49 +2944,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, @@ -109,9 +3009,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -119,49 +3019,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, @@ -184,9 +3084,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -194,9 +3094,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, @@ -206,6 +3106,237 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ContextProviderName", + "type": "Type", + "tags": [], + "label": "ContextProviderName", + "description": [ + "\nContextProviderName used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.EventType", + "type": "Type", + "tags": [], + "label": "EventType", + "description": [ + "\nEvent Type used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.PossibleSchemaTypes", + "type": "Type", + "tags": [], + "label": "PossibleSchemaTypes", + "description": [ + "\nHelper to ensure the declared types match the schema types" + ], + "signature": [ + "Value extends string | Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaStringTypes", + "text": "AllowedSchemaStringTypes" + }, + " : Value extends number ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaNumberTypes", + "text": "AllowedSchemaNumberTypes" + }, + " : Value extends boolean ? \"boolean\" : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaTypes", + "text": "AllowedSchemaTypes" + } + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.RootSchema", + "type": "Type", + "tags": [], + "label": "RootSchema", + "description": [ + "\nSchema definition to match the structure of the properties provided.\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaMetaOptional", + "type": "Type", + "tags": [], + "label": "SchemaMetaOptional", + "description": [ + "\nEnforces { optional: true } if the value can be undefined" + ], + "signature": [ + "unknown extends Value ? { optional?: boolean | undefined; } : undefined extends Value ? { optional: true; } : { optional?: false | undefined; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.SchemaValue", + "type": "Type", + "tags": [], + "label": "SchemaValue", + "description": [ + "\nType that defines all the possible values that the Schema accepts.\nThese types definitions are helping to identify earlier the possible missing `properties` nesting when\nmanually defining the schemas." + ], + "signature": [ + "{ type: \"pass_through\"; _meta: { description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "; } | (unknown extends Value ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends (infer U)[] | readonly (infer U)[] ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " : NonNullable extends Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends object ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + ")" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.ShipperName", + "type": "Type", + "tags": [], + "label": "ShipperName", + "description": [ + "\nShipper Name used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-analytics-server", + "id": "def-common.TelemetryCounterType", + "type": "Type", + "tags": [], + "label": "TelemetryCounterType", + "description": [ + "\nIndicates if the event contains data about succeeded, failed or dropped events:\n- enqueued: The event was accepted and will be sent to the shippers when they become available (and opt-in === true).\n- sent_to_shipper: The event was sent to at least one shipper.\n- succeeded: The event was successfully sent by the shipper.\n- failed: There was an error when processing/shipping the event. Refer to the Telemetry Counter's code for the reason.\n- dropped: The event was dropped from the queue. Refer to the Telemetry Counter's code for the reason." + ], + "signature": [ + "\"succeeded\" | \"failed\" | \"enqueued\" | \"sent_to_shipper\" | \"dropped\"" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [] diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index b1281d75c3b3d..e90a091217ad8 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3 | 0 | 0 | 0 | +| 100 | 0 | 0 | 0 | ## Common +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 7de21c211151c..0e60a56e9cfce 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: 2024-06-18 +date: 2024-06-19 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 713977cd2472c..1bbdd8746f8f8 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: 2024-06-18 +date: 2024-06-19 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 f251d7a1c9350..6b76538ad3b79 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: 2024-06-18 +date: 2024-06-19 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 f981d646c6fb3..d83bda2ad887d 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: 2024-06-18 +date: 2024-06-19 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 bef8995e9654b..34097db0fd1ae 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: 2024-06-18 +date: 2024-06-19 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 16145d3c11faf..459d3ad7f0a1d 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_core_apps_browser_internal.devdocs.json index 4f9ba443d8311..d243920c1c1f9 100644 --- a/api_docs/kbn_core_apps_browser_internal.devdocs.json +++ b/api_docs/kbn_core_apps_browser_internal.devdocs.json @@ -380,9 +380,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -390,9 +390,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 18fcb5acd1646..deebf2082410e 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: 2024-06-18 +date: 2024-06-19 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 e08586791cb80..92c43aa8d20a8 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: 2024-06-18 +date: 2024-06-19 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 b295697eba559..e3bfe07de819c 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: 2024-06-18 +date: 2024-06-19 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 eee3e8ec637f9..83361db92ba26 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: 2024-06-18 +date: 2024-06-19 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 94aacc78b60c1..2d4abb8658498 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: 2024-06-18 +date: 2024-06-19 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 970a80356039f..5730e672d8684 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: 2024-06-18 +date: 2024-06-19 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 a3ee47d6811bf..0093286db5fb8 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: 2024-06-18 +date: 2024-06-19 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 1b9697f69616d..2c0c272df5213 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: 2024-06-18 +date: 2024-06-19 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 30cceca53d2eb..c9d891961606c 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: 2024-06-18 +date: 2024-06-19 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 cc6cb4c39c1c2..51221490afe8c 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: 2024-06-18 +date: 2024-06-19 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 12c6007f62848..2175735f414c9 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_core_chrome_browser.devdocs.json index 3972f64135013..66c2b4398c08c 100644 --- a/api_docs/kbn_core_chrome_browser.devdocs.json +++ b/api_docs/kbn_core_chrome_browser.devdocs.json @@ -3716,7 +3716,7 @@ "label": "AppDeepLinkId", "description": [], "signature": [ - "\"fleet\" | \"graph\" | \"ml\" | \"monitoring\" | \"metrics\" | \"management\" | \"synthetics\" | \"ux\" | \"apm\" | \"logs\" | \"profiling\" | \"dashboards\" | \"observabilityAIAssistant\" | \"home\" | \"canvas\" | \"integrations\" | \"discover\" | \"observability-overview\" | \"appSearch\" | \"dev_tools\" | \"maps\" | \"visualize\" | \"dev_tools:console\" | \"dev_tools:searchprofiler\" | \"dev_tools:painless_lab\" | \"dev_tools:grokdebugger\" | \"ml:notifications\" | \"ml:nodes\" | \"ml:overview\" | \"ml:memoryUsage\" | \"ml:settings\" | \"ml:dataVisualizer\" | \"ml:anomalyDetection\" | \"ml:anomalyExplorer\" | \"ml:singleMetricViewer\" | \"ml:dataDrift\" | \"ml:dataFrameAnalytics\" | \"ml:resultExplorer\" | \"ml:analyticsMap\" | \"ml:aiOps\" | \"ml:logRateAnalysis\" | \"ml:logPatternAnalysis\" | \"ml:changePointDetections\" | \"ml:modelManagement\" | \"ml:nodesOverview\" | \"ml:esqlDataVisualizer\" | \"ml:fileUpload\" | \"ml:indexDataVisualizer\" | \"ml:calendarSettings\" | \"ml:filterListsSettings\" | \"osquery\" | \"management:transform\" | \"management:watcher\" | \"management:cases\" | \"management:tags\" | \"management:maintenanceWindows\" | \"management:settings\" | \"management:dataViews\" | \"management:spaces\" | \"management:users\" | \"management:migrate_data\" | \"management:search_sessions\" | \"management:data_quality\" | \"management:filesManagement\" | \"management:roles\" | \"management:reporting\" | \"management:aiAssistantManagementSelection\" | \"management:securityAiAssistantManagement\" | \"management:observabilityAiAssistantManagement\" | \"management:api_keys\" | \"management:cross_cluster_replication\" | \"management:license_management\" | \"management:index_lifecycle_management\" | \"management:index_management\" | \"management:ingest_pipelines\" | \"management:jobsListLink\" | \"management:objects\" | \"management:pipelines\" | \"management:remote_clusters\" | \"management:role_mappings\" | \"management:rollup_jobs\" | \"management:snapshot_restore\" | \"management:triggersActions\" | \"management:triggersActionsConnectors\" | \"management:upgrade_assistant\" | \"enterpriseSearch\" | \"enterpriseSearchContent\" | \"enterpriseSearchApplications\" | \"enterpriseSearchAnalytics\" | \"workplaceSearch\" | \"serverlessElasticsearch\" | \"serverlessConnectors\" | \"searchPlayground\" | \"searchInferenceEndpoints\" | \"enterpriseSearchContent:connectors\" | \"enterpriseSearchContent:searchIndices\" | \"enterpriseSearchContent:webCrawlers\" | \"enterpriseSearchApplications:searchApplications\" | \"enterpriseSearchApplications:playground\" | \"appSearch:engines\" | \"observability-logs-explorer\" | \"observabilityOnboarding\" | \"slo\" | \"logs:settings\" | \"logs:stream\" | \"logs:log-categories\" | \"logs:anomalies\" | \"observability-overview:cases\" | \"observability-overview:alerts\" | \"observability-overview:rules\" | \"observability-overview:cases_create\" | \"observability-overview:cases_configure\" | \"metrics:settings\" | \"metrics:hosts\" | \"metrics:inventory\" | \"metrics:metrics-explorer\" | \"metrics:assetDetails\" | \"apm:traces\" | \"apm:dependencies\" | \"apm:service-map\" | \"apm:settings\" | \"apm:services\" | \"apm:service-groups-list\" | \"apm:storage-explorer\" | \"synthetics:overview\" | \"synthetics:certificates\" | \"profiling:stacktraces\" | \"profiling:flamegraphs\" | \"profiling:functions\" | \"securitySolutionUI\" | \"securitySolutionUI:\" | \"securitySolutionUI:cases\" | \"securitySolutionUI:alerts\" | \"securitySolutionUI:rules\" | \"securitySolutionUI:policy\" | \"securitySolutionUI:overview\" | \"securitySolutionUI:dashboards\" | \"securitySolutionUI:cases_create\" | \"securitySolutionUI:cases_configure\" | \"securitySolutionUI:hosts\" | \"securitySolutionUI:users\" | \"securitySolutionUI:cloud_defend-policies\" | \"securitySolutionUI:cloud_security_posture-dashboard\" | \"securitySolutionUI:cloud_security_posture-findings\" | \"securitySolutionUI:cloud_security_posture-benchmarks\" | \"securitySolutionUI:kubernetes\" | \"securitySolutionUI:network\" | \"securitySolutionUI:data_quality\" | \"securitySolutionUI:explore\" | \"securitySolutionUI:assets\" | \"securitySolutionUI:cloud_defend\" | \"securitySolutionUI:administration\" | \"securitySolutionUI:attack_discovery\" | \"securitySolutionUI:blocklist\" | \"securitySolutionUI:cloud_security_posture-rules\" | \"securitySolutionUI:detections\" | \"securitySolutionUI:detection_response\" | \"securitySolutionUI:endpoints\" | \"securitySolutionUI:event_filters\" | \"securitySolutionUI:exceptions\" | \"securitySolutionUI:host_isolation_exceptions\" | \"securitySolutionUI:hosts-all\" | \"securitySolutionUI:hosts-anomalies\" | \"securitySolutionUI:hosts-risk\" | \"securitySolutionUI:hosts-events\" | \"securitySolutionUI:hosts-sessions\" | \"securitySolutionUI:hosts-uncommon_processes\" | \"securitySolutionUI:investigations\" | \"securitySolutionUI:get_started\" | \"securitySolutionUI:machine_learning-landing\" | \"securitySolutionUI:network-anomalies\" | \"securitySolutionUI:network-dns\" | \"securitySolutionUI:network-events\" | \"securitySolutionUI:network-flows\" | \"securitySolutionUI:network-http\" | \"securitySolutionUI:network-tls\" | \"securitySolutionUI:response_actions_history\" | \"securitySolutionUI:rules-add\" | \"securitySolutionUI:rules-create\" | \"securitySolutionUI:rules-landing\" | \"securitySolutionUI:threat_intelligence\" | \"securitySolutionUI:timelines\" | \"securitySolutionUI:timelines-templates\" | \"securitySolutionUI:trusted_apps\" | \"securitySolutionUI:users-all\" | \"securitySolutionUI:users-anomalies\" | \"securitySolutionUI:users-authentications\" | \"securitySolutionUI:users-events\" | \"securitySolutionUI:users-risk\" | \"securitySolutionUI:entity_analytics\" | \"securitySolutionUI:entity_analytics-management\" | \"securitySolutionUI:entity_analytics-asset-classification\" | \"securitySolutionUI:coverage-overview\" | \"fleet:settings\" | \"fleet:policies\" | \"fleet:data_streams\" | \"fleet:enrollment_tokens\" | \"fleet:uninstall_tokens\" | \"fleet:agents\"" + "\"fleet\" | \"graph\" | \"ml\" | \"monitoring\" | \"metrics\" | \"management\" | \"synthetics\" | \"ux\" | \"apm\" | \"logs\" | \"profiling\" | \"dashboards\" | \"observabilityAIAssistant\" | \"home\" | \"canvas\" | \"integrations\" | \"discover\" | \"observability-overview\" | \"appSearch\" | \"dev_tools\" | \"maps\" | \"visualize\" | \"dev_tools:console\" | \"dev_tools:searchprofiler\" | \"dev_tools:painless_lab\" | \"dev_tools:grokdebugger\" | \"ml:notifications\" | \"ml:nodes\" | \"ml:overview\" | \"ml:memoryUsage\" | \"ml:settings\" | \"ml:dataVisualizer\" | \"ml:anomalyDetection\" | \"ml:anomalyExplorer\" | \"ml:singleMetricViewer\" | \"ml:dataDrift\" | \"ml:dataFrameAnalytics\" | \"ml:resultExplorer\" | \"ml:analyticsMap\" | \"ml:aiOps\" | \"ml:logRateAnalysis\" | \"ml:logPatternAnalysis\" | \"ml:changePointDetections\" | \"ml:modelManagement\" | \"ml:nodesOverview\" | \"ml:esqlDataVisualizer\" | \"ml:fileUpload\" | \"ml:indexDataVisualizer\" | \"ml:calendarSettings\" | \"ml:filterListsSettings\" | \"osquery\" | \"management:transform\" | \"management:watcher\" | \"management:cases\" | \"management:tags\" | \"management:maintenanceWindows\" | \"management:settings\" | \"management:dataViews\" | \"management:spaces\" | \"management:users\" | \"management:migrate_data\" | \"management:search_sessions\" | \"management:data_quality\" | \"management:filesManagement\" | \"management:roles\" | \"management:reporting\" | \"management:aiAssistantManagementSelection\" | \"management:securityAiAssistantManagement\" | \"management:observabilityAiAssistantManagement\" | \"management:api_keys\" | \"management:cross_cluster_replication\" | \"management:license_management\" | \"management:index_lifecycle_management\" | \"management:index_management\" | \"management:ingest_pipelines\" | \"management:jobsListLink\" | \"management:objects\" | \"management:pipelines\" | \"management:remote_clusters\" | \"management:role_mappings\" | \"management:rollup_jobs\" | \"management:snapshot_restore\" | \"management:triggersActions\" | \"management:triggersActionsConnectors\" | \"management:upgrade_assistant\" | \"enterpriseSearch\" | \"enterpriseSearchContent\" | \"enterpriseSearchApplications\" | \"enterpriseSearchAnalytics\" | \"workplaceSearch\" | \"serverlessElasticsearch\" | \"serverlessConnectors\" | \"searchPlayground\" | \"searchInferenceEndpoints\" | \"enterpriseSearchContent:connectors\" | \"enterpriseSearchContent:searchIndices\" | \"enterpriseSearchContent:webCrawlers\" | \"enterpriseSearchApplications:searchApplications\" | \"enterpriseSearchApplications:playground\" | \"appSearch:engines\" | \"observability-logs-explorer\" | \"observabilityOnboarding\" | \"slo\" | \"logs:settings\" | \"logs:stream\" | \"logs:log-categories\" | \"logs:anomalies\" | \"observability-overview:cases\" | \"observability-overview:alerts\" | \"observability-overview:rules\" | \"observability-overview:cases_create\" | \"observability-overview:cases_configure\" | \"metrics:settings\" | \"metrics:hosts\" | \"metrics:inventory\" | \"metrics:metrics-explorer\" | \"metrics:assetDetails\" | \"apm:traces\" | \"apm:dependencies\" | \"apm:service-map\" | \"apm:settings\" | \"apm:services\" | \"apm:service-groups-list\" | \"apm:storage-explorer\" | \"synthetics:overview\" | \"synthetics:certificates\" | \"profiling:stacktraces\" | \"profiling:flamegraphs\" | \"profiling:functions\" | \"securitySolutionUI\" | \"securitySolutionUI:\" | \"securitySolutionUI:cases\" | \"securitySolutionUI:alerts\" | \"securitySolutionUI:rules\" | \"securitySolutionUI:policy\" | \"securitySolutionUI:overview\" | \"securitySolutionUI:dashboards\" | \"securitySolutionUI:cases_create\" | \"securitySolutionUI:cases_configure\" | \"securitySolutionUI:hosts\" | \"securitySolutionUI:users\" | \"securitySolutionUI:cloud_defend-policies\" | \"securitySolutionUI:cloud_security_posture-dashboard\" | \"securitySolutionUI:cloud_security_posture-findings\" | \"securitySolutionUI:cloud_security_posture-benchmarks\" | \"securitySolutionUI:kubernetes\" | \"securitySolutionUI:network\" | \"securitySolutionUI:data_quality\" | \"securitySolutionUI:explore\" | \"securitySolutionUI:assets\" | \"securitySolutionUI:cloud_defend\" | \"securitySolutionUI:administration\" | \"securitySolutionUI:attack_discovery\" | \"securitySolutionUI:blocklist\" | \"securitySolutionUI:cloud_security_posture-rules\" | \"securitySolutionUI:detections\" | \"securitySolutionUI:detection_response\" | \"securitySolutionUI:endpoints\" | \"securitySolutionUI:event_filters\" | \"securitySolutionUI:exceptions\" | \"securitySolutionUI:host_isolation_exceptions\" | \"securitySolutionUI:hosts-all\" | \"securitySolutionUI:hosts-anomalies\" | \"securitySolutionUI:hosts-risk\" | \"securitySolutionUI:hosts-events\" | \"securitySolutionUI:hosts-sessions\" | \"securitySolutionUI:hosts-uncommon_processes\" | \"securitySolutionUI:investigations\" | \"securitySolutionUI:get_started\" | \"securitySolutionUI:machine_learning-landing\" | \"securitySolutionUI:network-anomalies\" | \"securitySolutionUI:network-dns\" | \"securitySolutionUI:network-events\" | \"securitySolutionUI:network-flows\" | \"securitySolutionUI:network-http\" | \"securitySolutionUI:network-tls\" | \"securitySolutionUI:response_actions_history\" | \"securitySolutionUI:rules-add\" | \"securitySolutionUI:rules-create\" | \"securitySolutionUI:rules-landing\" | \"securitySolutionUI:threat_intelligence\" | \"securitySolutionUI:timelines\" | \"securitySolutionUI:timelines-templates\" | \"securitySolutionUI:trusted_apps\" | \"securitySolutionUI:users-all\" | \"securitySolutionUI:users-anomalies\" | \"securitySolutionUI:users-authentications\" | \"securitySolutionUI:users-events\" | \"securitySolutionUI:users-risk\" | \"securitySolutionUI:entity_analytics\" | \"securitySolutionUI:entity_analytics-management\" | \"securitySolutionUI:entity_analytics-asset-classification\" | \"securitySolutionUI:coverage-overview\" | \"securitySolutionUI:notes-management\" | \"fleet:settings\" | \"fleet:policies\" | \"fleet:data_streams\" | \"fleet:enrollment_tokens\" | \"fleet:uninstall_tokens\" | \"fleet:agents\"" ], "path": "packages/core/chrome/core-chrome-browser/src/project_navigation.ts", "deprecated": false, diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index df65336afe538..71105415fb4ca 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: 2024-06-18 +date: 2024-06-19 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 5381f189870cb..df950e030dec0 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: 2024-06-18 +date: 2024-06-19 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 6794b366689c1..9eec1a1692c15 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: 2024-06-18 +date: 2024-06-19 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 4ff34e4adefc2..2e6eebc20e1ab 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: 2024-06-18 +date: 2024-06-19 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 e81870b643c87..c499b048c9344 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: 2024-06-18 +date: 2024-06-19 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 6617eb567d073..df9652c4f6d7e 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: 2024-06-18 +date: 2024-06-19 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 d84a80e9e697b..9ce3fd7b27906 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: 2024-06-18 +date: 2024-06-19 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 7b61b93bf6cc9..23632cdbbd9ac 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: 2024-06-18 +date: 2024-06-19 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 31cfa4d4e45f9..d23c897cecffa 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: 2024-06-18 +date: 2024-06-19 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 bf2dd1174975c..6f258fcfc8b48 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: 2024-06-18 +date: 2024-06-19 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 2c5c656d5a173..90daf5fa734f3 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: 2024-06-18 +date: 2024-06-19 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 0eef07d37f2f6..f657bd0dc847e 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: 2024-06-18 +date: 2024-06-19 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 c48a04beced54..e5f76f49825dd 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: 2024-06-18 +date: 2024-06-19 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 368228a724450..9a20d9cb1f7fe 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: 2024-06-18 +date: 2024-06-19 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 189c9acfe34dc..92b19b1819557 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: 2024-06-18 +date: 2024-06-19 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 4f27d9d7bdc27..d5df05b865157 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: 2024-06-18 +date: 2024-06-19 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 a6780bf1df2ea..78e9a91330219 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: 2024-06-18 +date: 2024-06-19 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 40fdbe57f7aec..8336c45fbe0c2 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: 2024-06-18 +date: 2024-06-19 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 90d2f8adc9c27..cda2ac5294b20 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: 2024-06-18 +date: 2024-06-19 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 347b7e5ca7372..612ce5f4084cb 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: 2024-06-18 +date: 2024-06-19 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 1d06db5d65017..a65bfc25d7e6e 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: 2024-06-18 +date: 2024-06-19 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 dffaee0aef227..674666ba6ebd2 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: 2024-06-18 +date: 2024-06-19 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 078d393221f85..7904772ed2ae2 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: 2024-06-18 +date: 2024-06-19 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 1b33d6e1e1d43..e7d4c7a2ac357 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: 2024-06-18 +date: 2024-06-19 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 78c2fb36d6e18..5e73f0659d04b 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: 2024-06-18 +date: 2024-06-19 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 81c7b543e5a39..75bcf0def4b57 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: 2024-06-18 +date: 2024-06-19 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 e9c8b9fb706e4..5eb9304aac317 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: 2024-06-18 +date: 2024-06-19 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 201c9d3d19e46..8ba4a516a391b 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: 2024-06-18 +date: 2024-06-19 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 3a7e7795ab0de..2770e6e0bf0cb 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: 2024-06-18 +date: 2024-06-19 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 56201fe91ba97..338cfc8f178ab 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: 2024-06-18 +date: 2024-06-19 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 d8f2b10177c2a..7bd144d8c9668 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: 2024-06-18 +date: 2024-06-19 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 2b252e07e3385..2943e8c03296f 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: 2024-06-18 +date: 2024-06-19 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 66a96931f2fcc..5778a1ec26183 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: 2024-06-18 +date: 2024-06-19 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 dab20d8cc1900..485e7e1e79c36 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: 2024-06-18 +date: 2024-06-19 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 0563ccd1b8165..1dc6be712cf05 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: 2024-06-18 +date: 2024-06-19 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 12072174cb8f0..8dd268062f9c7 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: 2024-06-18 +date: 2024-06-19 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 acef91e377e5e..2b593020653fd 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: 2024-06-18 +date: 2024-06-19 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 6cd249cc3e4df..cf2c050db360b 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: 2024-06-18 +date: 2024-06-19 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 4e94ae5e5a8f1..77688dedbcd7a 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: 2024-06-18 +date: 2024-06-19 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 6c1070c0eaf01..565afd6b084f1 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: 2024-06-18 +date: 2024-06-19 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 8fc34ad8c65e1..0558d5a0eed69 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: 2024-06-18 +date: 2024-06-19 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 44fc25a15d19e..5f7488eb7179f 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: 2024-06-18 +date: 2024-06-19 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 abb6ef5226309..afd1291384dd2 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: 2024-06-18 +date: 2024-06-19 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.mdx b/api_docs/kbn_core_http_resources_server.mdx index dcca80ea28e06..a0f4412ee86e1 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: 2024-06-18 +date: 2024-06-19 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 509693ecd745a..94f41e2228c56 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: 2024-06-18 +date: 2024-06-19 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.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 8a70bb7f215a6..aded1566dcffd 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: 2024-06-18 +date: 2024-06-19 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 91c3ad7da3110..3debd264e8662 100644 --- a/api_docs/kbn_core_http_router_server_internal.devdocs.json +++ b/api_docs/kbn_core_http_router_server_internal.devdocs.json @@ -187,7 +187,7 @@ }, "<", "Method", - ">, \"description\" | \"access\"> | undefined; access: ", + ">, \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -195,7 +195,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts", "deprecated": false, @@ -266,7 +266,7 @@ }, "<", "Method", - ">, \"description\" | \"access\"> | undefined; access: ", + ">, \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -274,7 +274,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts", "deprecated": false, @@ -345,7 +345,7 @@ }, "<", "Method", - ">, \"description\" | \"access\"> | undefined; access: ", + ">, \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -353,7 +353,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts", "deprecated": false, @@ -424,7 +424,7 @@ }, "<", "Method", - ">, \"description\" | \"access\"> | undefined; access: ", + ">, \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -432,7 +432,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts", "deprecated": false, @@ -503,7 +503,7 @@ }, "<", "Method", - ">, \"description\" | \"access\"> | undefined; access: ", + ">, \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -511,7 +511,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index c7b81733f4991..dcdcbc84d6529 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.devdocs.json b/api_docs/kbn_core_http_router_server_mocks.devdocs.json index ee55bc61e06d3..de2f1580a0cb2 100644 --- a/api_docs/kbn_core_http_router_server_mocks.devdocs.json +++ b/api_docs/kbn_core_http_router_server_mocks.devdocs.json @@ -80,7 +80,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -88,7 +88,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index ee3e10bf45147..f5d32c20ea099 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: 2024-06-18 +date: 2024-06-19 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 afadd6b9e7134..6efa1875aa8c9 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -3510,6 +3510,10 @@ "plugin": "@kbn/core-apps-server-internal", "path": "packages/core/apps/core-apps-server-internal/src/core_app.ts" }, + { + "plugin": "usageCollection", + "path": "src/plugins/usage_collection/server/routes/stats/stats.ts" + }, { "plugin": "licensing", "path": "x-pack/plugins/licensing/server/routes/info.ts" @@ -3522,10 +3526,6 @@ "plugin": "features", "path": "x-pack/plugins/features/server/routes/index.ts" }, - { - "plugin": "usageCollection", - "path": "src/plugins/usage_collection/server/routes/stats/stats.ts" - }, { "plugin": "customIntegrations", "path": "src/plugins/custom_integrations/server/routes/define_routes.ts" @@ -6180,6 +6180,10 @@ "plugin": "@kbn/core-capabilities-server-internal", "path": "packages/core/capabilities/core-capabilities-server-internal/src/routes/resolve_capabilities.ts" }, + { + "plugin": "usageCollection", + "path": "src/plugins/usage_collection/server/routes/ui_counters.ts" + }, { "plugin": "licensing", "path": "x-pack/plugins/licensing/server/routes/internal/notify_feature_usage.ts" @@ -6188,10 +6192,6 @@ "plugin": "licensing", "path": "x-pack/plugins/licensing/server/routes/internal/register_feature.ts" }, - { - "plugin": "usageCollection", - "path": "src/plugins/usage_collection/server/routes/ui_counters.ts" - }, { "plugin": "home", "path": "src/plugins/home/server/services/sample_data/routes/install.ts" @@ -12610,6 +12610,22 @@ "path": "packages/core/http/core-http-server/src/router/route.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-http-server", + "id": "def-common.RouteConfigOptions.deprecated", + "type": "CompoundType", + "tags": [], + "label": "deprecated", + "description": [ + "\nSetting this to `true` declares this route to be deprecated. Consumers SHOULD\nrefrain from usage of this route.\n" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/http/core-http-server/src/router/route.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -14327,6 +14343,10 @@ "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/routes/anonymization_fields/find_route.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/find_route.ts" + }, { "plugin": "logsShared", "path": "x-pack/plugins/observability_solution/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -14619,6 +14639,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/privileges.ts" @@ -14906,7 +14930,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -14914,7 +14938,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -15197,7 +15221,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -15205,7 +15229,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -15721,6 +15745,14 @@ "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/routes/anonymization_fields/bulk_actions_route.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/bulk_actions_route.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/create_route.ts" + }, { "plugin": "logsShared", "path": "x-pack/plugins/observability_solution/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -16005,6 +16037,14 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" @@ -16125,10 +16165,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/observability_solution/synthetics/server/server.ts" }, - { - "plugin": "elasticAssistant", - "path": "x-pack/plugins/elastic_assistant/server/routes/knowledge_base/entries/create_route.ts" - }, { "plugin": "controls", "path": "src/plugins/controls/server/options_list/options_list_suggestions_route.ts" @@ -16236,7 +16272,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -16244,7 +16280,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -16371,7 +16407,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -16379,7 +16415,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -16583,6 +16619,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts" + }, { "plugin": "synthetics", "path": "x-pack/plugins/observability_solution/synthetics/server/server.ts" @@ -16638,7 +16678,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -16646,7 +16686,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -19341,7 +19381,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -19349,7 +19389,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -19417,7 +19457,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"description\" | \"access\"> | undefined; access: ", + ", \"description\" | \"deprecated\" | \"access\"> | undefined; access: ", { "pluginId": "@kbn/core-http-server", "scope": "common", @@ -19425,7 +19465,7 @@ "section": "def-common.RouteAccess", "text": "RouteAccess" }, - "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; }" + "; enableQueryVersion?: boolean | undefined; summary?: string | undefined; description?: string | undefined; deprecated?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index c59369bdb598a..3d4ca4db80615 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: 2024-06-18 +date: 2024-06-19 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 | |-------------------|-----------|------------------------|-----------------| -| 488 | 2 | 193 | 0 | +| 489 | 2 | 193 | 0 | ## Common diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 94a84e11ee872..403fc01ea0b4d 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: 2024-06-18 +date: 2024-06-19 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 398c4b490aeff..2c11130958d72 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: 2024-06-18 +date: 2024-06-19 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 cef2050e92def..293fa964ee4a5 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: 2024-06-18 +date: 2024-06-19 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 a0e66b8eab87c..b65b47da9991e 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: 2024-06-18 +date: 2024-06-19 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 5fc017df1af97..1078b9422550d 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: 2024-06-18 +date: 2024-06-19 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 7942a398e549b..6e63af728c086 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: 2024-06-18 +date: 2024-06-19 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 95e656990580d..399f8f707f150 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: 2024-06-18 +date: 2024-06-19 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 00307bd30d48f..e09f4d57977fd 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: 2024-06-18 +date: 2024-06-19 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 9a3d9633892ee..53e799d45f330 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: 2024-06-18 +date: 2024-06-19 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 30f7e9f75dbfc..742fb3ae3e247 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_core_lifecycle_browser.devdocs.json index 249fb73e18a74..ad2d7ba96eb1f 100644 --- a/api_docs/kbn_core_lifecycle_browser.devdocs.json +++ b/api_docs/kbn_core_lifecycle_browser.devdocs.json @@ -55,9 +55,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -65,49 +65,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, @@ -437,9 +437,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -447,9 +447,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index b0c301e1425d0..bfeb9a0c6fa54 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: 2024-06-18 +date: 2024-06-19 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 ddec0ce7847f4..3e3d6f9103061 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_core_lifecycle_server.devdocs.json index 39e4ac4c5f031..b52260d08327c 100644 --- a/api_docs/kbn_core_lifecycle_server.devdocs.json +++ b/api_docs/kbn_core_lifecycle_server.devdocs.json @@ -45,9 +45,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -55,49 +55,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, @@ -220,9 +220,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -230,49 +230,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, @@ -727,9 +727,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -737,9 +737,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index 7ec9130a81c25..540a363e5f08a 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: 2024-06-18 +date: 2024-06-19 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 9d93dec58ef0b..bcd4440d8c427 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: 2024-06-18 +date: 2024-06-19 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 d75280e591054..ebe1d709f3626 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: 2024-06-18 +date: 2024-06-19 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 1528d1873342d..81ced9b396fd3 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: 2024-06-18 +date: 2024-06-19 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.mdx b/api_docs/kbn_core_logging_server.mdx index a9e1c8beb172a..462ee206a17ea 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: 2024-06-18 +date: 2024-06-19 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.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 09c173f792ef9..547d8e1f274c3 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: 2024-06-18 +date: 2024-06-19 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 272ce8ea971a3..46007186a4cf7 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: 2024-06-18 +date: 2024-06-19 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 767835c5efb7d..18e66be6b7a3c 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: 2024-06-18 +date: 2024-06-19 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 7f46853993532..464491aa5691d 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: 2024-06-18 +date: 2024-06-19 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 741ada6511119..e01424863afb0 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: 2024-06-18 +date: 2024-06-19 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 20cc76f5b09ef..ab8dd8c9df904 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: 2024-06-18 +date: 2024-06-19 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 e99b6d6168e72..3ec6efa109800 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: 2024-06-18 +date: 2024-06-19 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 0214af178c9f0..61f1267a833b8 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: 2024-06-18 +date: 2024-06-19 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 65540f3457897..83f6a6541d425 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: 2024-06-18 +date: 2024-06-19 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 61f89ff5f2cb3..380f12a5efa54 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: 2024-06-18 +date: 2024-06-19 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 ec3d7f9b86129..7f2fd98b2ad18 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: 2024-06-18 +date: 2024-06-19 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 79310036bbe9a..260678120bf7b 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: 2024-06-18 +date: 2024-06-19 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 a3998cca34a3a..19a018e82aa93 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: 2024-06-18 +date: 2024-06-19 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 45310c0840b60..a37cddaa83ce9 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: 2024-06-18 +date: 2024-06-19 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 c85edd3257f91..4e07e307cd3ef 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: 2024-06-18 +date: 2024-06-19 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 3393b2a402121..ce21d35d70b63 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: 2024-06-18 +date: 2024-06-19 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 5d69b7ee580e0..3ffde560b9cb8 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: 2024-06-18 +date: 2024-06-19 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 f0cae503b4f1c..394a55506fc30 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: 2024-06-18 +date: 2024-06-19 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 99d1abe125a68..0f2265927f8e9 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: 2024-06-18 +date: 2024-06-19 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_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index 6c97ce67d86a4..2f74db77bc206 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index 88aba70f77925..36ded0cd67d6c 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 247f7c8135214..568715e2a0baa 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: 2024-06-18 +date: 2024-06-19 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 0810e0ba2d759..f0ffacb8de493 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: 2024-06-18 +date: 2024-06-19 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 a1ad60f25d392..ae491b22583cf 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: 2024-06-18 +date: 2024-06-19 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 f20648b50a0b1..42345a0163255 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: 2024-06-18 +date: 2024-06-19 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 5de01f17af371..8880edcde44d2 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: 2024-06-18 +date: 2024-06-19 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 5fb49017a9158..f50b1493d6bc0 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: 2024-06-18 +date: 2024-06-19 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 4291832fd0738..c602f636b9874 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: 2024-06-18 +date: 2024-06-19 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 a6dcf012a3253..7cb65d62fa0d1 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: 2024-06-18 +date: 2024-06-19 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 fba55c27a9059..9f91e8923304d 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: 2024-06-18 +date: 2024-06-19 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 1f4246ce25225..874e3e0bdd0ea 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: 2024-06-18 +date: 2024-06-19 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_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index c313d47ec8a2f..ecffad213e4ff 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: 2024-06-18 +date: 2024-06-19 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 df005b36ab161..e0cc5522906d0 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: 2024-06-18 +date: 2024-06-19 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 6a03625c7cbec..0c5b314f1f660 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: 2024-06-18 +date: 2024-06-19 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 ebe9f47d41e46..752ecbf87d7e6 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: 2024-06-18 +date: 2024-06-19 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 2eddae6645152..c433502eed430 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: 2024-06-18 +date: 2024-06-19 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 820ca0283b29e..35a7a834c69bc 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: 2024-06-18 +date: 2024-06-19 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.mdx b/api_docs/kbn_core_saved_objects_common.mdx index b4ba29e7cd7ac..68d6a67769611 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: 2024-06-18 +date: 2024-06-19 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 318f934666135..4a1337ba6374f 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: 2024-06-18 +date: 2024-06-19 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 61bd3b20ba212..8e6a4bbac0003 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: 2024-06-18 +date: 2024-06-19 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 007e6d0007869..80a214f8e8bcc 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: 2024-06-18 +date: 2024-06-19 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 b287508e816f6..e4c15b37732ab 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: 2024-06-18 +date: 2024-06-19 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 e60781764e9dd..78665054e2d51 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: 2024-06-18 +date: 2024-06-19 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 0ebdb8b26557d..98fc56e33289f 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: 2024-06-18 +date: 2024-06-19 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 4b2a55c6e396c..19151bb337527 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: 2024-06-18 +date: 2024-06-19 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 43cfbead9833d..ff2d640d3dff1 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: 2024-06-18 +date: 2024-06-19 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_security_browser.mdx b/api_docs/kbn_core_security_browser.mdx index 5be1e78d5da9d..0918bd4435b48 100644 --- a/api_docs/kbn_core_security_browser.mdx +++ b/api_docs/kbn_core_security_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser title: "@kbn/core-security-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser'] --- import kbnCoreSecurityBrowserObj from './kbn_core_security_browser.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_internal.mdx b/api_docs/kbn_core_security_browser_internal.mdx index 991a583cc5e12..bb1ed61f82173 100644 --- a/api_docs/kbn_core_security_browser_internal.mdx +++ b/api_docs/kbn_core_security_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-internal title: "@kbn/core-security-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-internal plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-internal'] --- import kbnCoreSecurityBrowserInternalObj from './kbn_core_security_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_mocks.mdx b/api_docs/kbn_core_security_browser_mocks.mdx index c3c1737fdc9ab..300d673be9d5c 100644 --- a/api_docs/kbn_core_security_browser_mocks.mdx +++ b/api_docs/kbn_core_security_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-mocks title: "@kbn/core-security-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-mocks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-mocks'] --- import kbnCoreSecurityBrowserMocksObj from './kbn_core_security_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_security_common.mdx b/api_docs/kbn_core_security_common.mdx index 9670c5a59d448..5078e7aac7003 100644 --- a/api_docs/kbn_core_security_common.mdx +++ b/api_docs/kbn_core_security_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-common title: "@kbn/core-security-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-common'] --- import kbnCoreSecurityCommonObj from './kbn_core_security_common.devdocs.json'; diff --git a/api_docs/kbn_core_security_server.mdx b/api_docs/kbn_core_security_server.mdx index 35be18d36b158..84c9098187bbb 100644 --- a/api_docs/kbn_core_security_server.mdx +++ b/api_docs/kbn_core_security_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server title: "@kbn/core-security-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server'] --- import kbnCoreSecurityServerObj from './kbn_core_security_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_internal.mdx b/api_docs/kbn_core_security_server_internal.mdx index 3b0ec3fe78699..2bd601031c0c3 100644 --- a/api_docs/kbn_core_security_server_internal.mdx +++ b/api_docs/kbn_core_security_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-internal title: "@kbn/core-security-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-internal plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-internal'] --- import kbnCoreSecurityServerInternalObj from './kbn_core_security_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_mocks.mdx b/api_docs/kbn_core_security_server_mocks.mdx index ac515de31e89e..7c7d458c61b64 100644 --- a/api_docs/kbn_core_security_server_mocks.mdx +++ b/api_docs/kbn_core_security_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-mocks title: "@kbn/core-security-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-mocks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-mocks'] --- import kbnCoreSecurityServerMocksObj from './kbn_core_security_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index dc33a315941e4..b2be2d573a383 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: 2024-06-18 +date: 2024-06-19 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 b843121cbd69a..a4e723953e857 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: 2024-06-18 +date: 2024-06-19 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 ed4b208f4a796..226d66fd93b4c 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_core_status_server_internal.devdocs.json index 107828999c77f..5a27f026247ba 100644 --- a/api_docs/kbn_core_status_server_internal.devdocs.json +++ b/api_docs/kbn_core_status_server_internal.devdocs.json @@ -296,9 +296,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -306,49 +306,49 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, ">; registerEventType: (eventTypeOps: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.EventTypeOpts", "text": "EventTypeOpts" }, ") => void; registerShipper: (Shipper: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ShipperClassConstructor", "text": "ShipperClassConstructor" }, ", shipperConfig: ShipperConfig, opts?: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.RegisterShipperOpts", "text": "RegisterShipperOpts" }, " | undefined) => void; registerContextProvider: (contextProviderOpts: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.ContextProviderOpts", "text": "ContextProviderOpts" }, diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 71ea68f7d5ba9..fc208bda2f92b 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: 2024-06-18 +date: 2024-06-19 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 cc69f9a7c8175..da52f2f53ee6d 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: 2024-06-18 +date: 2024-06-19 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 0b27924382ad5..57d54bc469e26 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: 2024-06-18 +date: 2024-06-19 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 f937cd2d8a0a8..7dbb268d367bc 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: 2024-06-18 +date: 2024-06-19 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 ac242965cda10..1bceadbf6500e 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: 2024-06-18 +date: 2024-06-19 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_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index 7a5d6babab383..80dfcec841e4f 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.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 bc9bd5e604519..b5397439e4a13 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: 2024-06-18 +date: 2024-06-19 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 e21547444a200..08ee975d23ec6 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: 2024-06-18 +date: 2024-06-19 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 1c73e73b8e24d..3a8b9886f7f8a 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: 2024-06-18 +date: 2024-06-19 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_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 9762a0bf00d2f..888ce7638b70b 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: 2024-06-18 +date: 2024-06-19 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 6fc4bbaceccfa..d2fe1dfd87a1b 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: 2024-06-18 +date: 2024-06-19 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 098a43228e211..a80cfcb497d84 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: 2024-06-18 +date: 2024-06-19 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 a678369d6eb6c..2f7cad133b4cd 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: 2024-06-18 +date: 2024-06-19 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 50f6a33ada34e..fd3819d87139b 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: 2024-06-18 +date: 2024-06-19 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 ae5457505b377..776cd00c33ba9 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: 2024-06-18 +date: 2024-06-19 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 dda6040547258..66a0252c0743c 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: 2024-06-18 +date: 2024-06-19 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 50bc027717952..44ffdbee19eed 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: 2024-06-18 +date: 2024-06-19 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 9f5d7558f0cde..8c86d7d90a81d 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: 2024-06-18 +date: 2024-06-19 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 44e691739a9a4..167711a91f528 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: 2024-06-18 +date: 2024-06-19 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 b5853c26912dd..91b5b01cc15bf 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: 2024-06-18 +date: 2024-06-19 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_core_user_profile_browser.mdx b/api_docs/kbn_core_user_profile_browser.mdx index 3f847bb3cbb7b..eb95315c988d1 100644 --- a/api_docs/kbn_core_user_profile_browser.mdx +++ b/api_docs/kbn_core_user_profile_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser title: "@kbn/core-user-profile-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser'] --- import kbnCoreUserProfileBrowserObj from './kbn_core_user_profile_browser.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_internal.mdx b/api_docs/kbn_core_user_profile_browser_internal.mdx index bbcb96fe8d840..c843246a61a82 100644 --- a/api_docs/kbn_core_user_profile_browser_internal.mdx +++ b/api_docs/kbn_core_user_profile_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-internal title: "@kbn/core-user-profile-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-internal plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-internal'] --- import kbnCoreUserProfileBrowserInternalObj from './kbn_core_user_profile_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_mocks.mdx b/api_docs/kbn_core_user_profile_browser_mocks.mdx index c95de8602f92e..befa003474b26 100644 --- a/api_docs/kbn_core_user_profile_browser_mocks.mdx +++ b/api_docs/kbn_core_user_profile_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-mocks title: "@kbn/core-user-profile-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-mocks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-mocks'] --- import kbnCoreUserProfileBrowserMocksObj from './kbn_core_user_profile_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_common.mdx b/api_docs/kbn_core_user_profile_common.mdx index e76fb89ad8be0..f66ad47be6122 100644 --- a/api_docs/kbn_core_user_profile_common.mdx +++ b/api_docs/kbn_core_user_profile_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-common title: "@kbn/core-user-profile-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-common'] --- import kbnCoreUserProfileCommonObj from './kbn_core_user_profile_common.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server.mdx b/api_docs/kbn_core_user_profile_server.mdx index ef92831535c47..0e15c25f306cb 100644 --- a/api_docs/kbn_core_user_profile_server.mdx +++ b/api_docs/kbn_core_user_profile_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server title: "@kbn/core-user-profile-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server'] --- import kbnCoreUserProfileServerObj from './kbn_core_user_profile_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_internal.mdx b/api_docs/kbn_core_user_profile_server_internal.mdx index 422f1ce5a92bb..41d57e14eb86d 100644 --- a/api_docs/kbn_core_user_profile_server_internal.mdx +++ b/api_docs/kbn_core_user_profile_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-internal title: "@kbn/core-user-profile-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-internal plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-internal'] --- import kbnCoreUserProfileServerInternalObj from './kbn_core_user_profile_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_mocks.mdx b/api_docs/kbn_core_user_profile_server_mocks.mdx index 6e82292c8f67a..b86eb701b873f 100644 --- a/api_docs/kbn_core_user_profile_server_mocks.mdx +++ b/api_docs/kbn_core_user_profile_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-mocks title: "@kbn/core-user-profile-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-mocks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-mocks'] --- import kbnCoreUserProfileServerMocksObj from './kbn_core_user_profile_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index bb2abf7052d1a..795d69dbb69e3 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index e0530e82a349c..a3aa62ecb7342 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 8d6830288901c..0738623f9c4cd 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: 2024-06-18 +date: 2024-06-19 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 34122d21f5558..a222beae12053 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index 5c9edfafda6dd..6bb317fa407d4 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 2a1a10905c5e9..368d1d7209818 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 24d57726f53c4..e3da1a3651de5 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_forge.mdx b/api_docs/kbn_data_forge.mdx index 6c552996443a5..aef3c64f67757 100644 --- a/api_docs/kbn_data_forge.mdx +++ b/api_docs/kbn_data_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-forge title: "@kbn/data-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-forge plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-forge'] --- import kbnDataForgeObj from './kbn_data_forge.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 56d6b807dcf96..932436e20308e 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_data_stream_adapter.mdx b/api_docs/kbn_data_stream_adapter.mdx index d7755afb4bd0c..50998407ddbfe 100644 --- a/api_docs/kbn_data_stream_adapter.mdx +++ b/api_docs/kbn_data_stream_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-stream-adapter title: "@kbn/data-stream-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-stream-adapter plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-stream-adapter'] --- import kbnDataStreamAdapterObj from './kbn_data_stream_adapter.devdocs.json'; diff --git a/api_docs/kbn_data_view_utils.devdocs.json b/api_docs/kbn_data_view_utils.devdocs.json index 0bacfe7a0aa46..bbef9faf79cd5 100644 --- a/api_docs/kbn_data_view_utils.devdocs.json +++ b/api_docs/kbn_data_view_utils.devdocs.json @@ -18,7 +18,74 @@ }, "common": { "classes": [], - "functions": [], + "functions": [ + { + "parentPluginId": "@kbn/data-view-utils", + "id": "def-common.createRegExpPatternFrom", + "type": "Function", + "tags": [], + "label": "createRegExpPatternFrom", + "description": [], + "signature": [ + "(basePatterns: string | string[]) => RegExp" + ], + "path": "packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/data-view-utils", + "id": "def-common.createRegExpPatternFrom.$1", + "type": "CompoundType", + "tags": [], + "label": "basePatterns", + "description": [], + "signature": [ + "string | string[]" + ], + "path": "packages/kbn-data-view-utils/src/utils/create_regexp_pattern_from.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/data-view-utils", + "id": "def-common.testPatternAgainstAllowedList", + "type": "Function", + "tags": [], + "label": "testPatternAgainstAllowedList", + "description": [], + "signature": [ + "(allowedList: (string | RegExp)[]) => (value: string) => boolean" + ], + "path": "packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/data-view-utils", + "id": "def-common.testPatternAgainstAllowedList.$1", + "type": "Array", + "tags": [], + "label": "allowedList", + "description": [], + "signature": [ + "(string | RegExp)[]" + ], + "path": "packages/kbn-data-view-utils/src/utils/test_pattern_against_allowed_list.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], "interfaces": [], "enums": [], "misc": [ diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index 3f9cfd3e15bac..e03b8bc0f9617 100644 --- a/api_docs/kbn_data_view_utils.mdx +++ b/api_docs/kbn_data_view_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-view-utils title: "@kbn/data-view-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-view-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1 | 0 | 0 | 0 | +| 5 | 0 | 4 | 0 | ## Common +### Functions + + ### Consts, variables and types diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 9bb9de5ed5471..e90b3a3e04981 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index 6f5b8882c4f5a..3db3b8868e8a1 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index f4757ad7d1876..08891eda96b5f 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_fleet.mdx b/api_docs/kbn_deeplinks_fleet.mdx index 96f0c8c0341cb..2b6f29f578e49 100644 --- a/api_docs/kbn_deeplinks_fleet.mdx +++ b/api_docs/kbn_deeplinks_fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-fleet title: "@kbn/deeplinks-fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-fleet plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-fleet'] --- import kbnDeeplinksFleetObj from './kbn_deeplinks_fleet.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index 8b229f4cc19f8..31971c1739ba7 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index cc069e178f4bc..7a2fe8066cfa9 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index d824e8064b963..672f113f92ac8 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 555bbbf62fdc2..43a1345190c31 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_security.devdocs.json b/api_docs/kbn_deeplinks_security.devdocs.json index 1e9a52bf2b368..5eec00a0d9340 100644 --- a/api_docs/kbn_deeplinks_security.devdocs.json +++ b/api_docs/kbn_deeplinks_security.devdocs.json @@ -58,7 +58,7 @@ "label": "DeepLinkId", "description": [], "signature": [ - "\"securitySolutionUI\" | \"securitySolutionUI:\" | \"securitySolutionUI:cases\" | \"securitySolutionUI:alerts\" | \"securitySolutionUI:rules\" | \"securitySolutionUI:policy\" | \"securitySolutionUI:overview\" | \"securitySolutionUI:dashboards\" | \"securitySolutionUI:cases_create\" | \"securitySolutionUI:cases_configure\" | \"securitySolutionUI:hosts\" | \"securitySolutionUI:users\" | \"securitySolutionUI:cloud_defend-policies\" | \"securitySolutionUI:cloud_security_posture-dashboard\" | \"securitySolutionUI:cloud_security_posture-findings\" | \"securitySolutionUI:cloud_security_posture-benchmarks\" | \"securitySolutionUI:kubernetes\" | \"securitySolutionUI:network\" | \"securitySolutionUI:data_quality\" | \"securitySolutionUI:explore\" | \"securitySolutionUI:assets\" | \"securitySolutionUI:cloud_defend\" | \"securitySolutionUI:administration\" | \"securitySolutionUI:attack_discovery\" | \"securitySolutionUI:blocklist\" | \"securitySolutionUI:cloud_security_posture-rules\" | \"securitySolutionUI:detections\" | \"securitySolutionUI:detection_response\" | \"securitySolutionUI:endpoints\" | \"securitySolutionUI:event_filters\" | \"securitySolutionUI:exceptions\" | \"securitySolutionUI:host_isolation_exceptions\" | \"securitySolutionUI:hosts-all\" | \"securitySolutionUI:hosts-anomalies\" | \"securitySolutionUI:hosts-risk\" | \"securitySolutionUI:hosts-events\" | \"securitySolutionUI:hosts-sessions\" | \"securitySolutionUI:hosts-uncommon_processes\" | \"securitySolutionUI:investigations\" | \"securitySolutionUI:get_started\" | \"securitySolutionUI:machine_learning-landing\" | \"securitySolutionUI:network-anomalies\" | \"securitySolutionUI:network-dns\" | \"securitySolutionUI:network-events\" | \"securitySolutionUI:network-flows\" | \"securitySolutionUI:network-http\" | \"securitySolutionUI:network-tls\" | \"securitySolutionUI:response_actions_history\" | \"securitySolutionUI:rules-add\" | \"securitySolutionUI:rules-create\" | \"securitySolutionUI:rules-landing\" | \"securitySolutionUI:threat_intelligence\" | \"securitySolutionUI:timelines\" | \"securitySolutionUI:timelines-templates\" | \"securitySolutionUI:trusted_apps\" | \"securitySolutionUI:users-all\" | \"securitySolutionUI:users-anomalies\" | \"securitySolutionUI:users-authentications\" | \"securitySolutionUI:users-events\" | \"securitySolutionUI:users-risk\" | \"securitySolutionUI:entity_analytics\" | \"securitySolutionUI:entity_analytics-management\" | \"securitySolutionUI:entity_analytics-asset-classification\" | \"securitySolutionUI:coverage-overview\"" + "\"securitySolutionUI\" | \"securitySolutionUI:\" | \"securitySolutionUI:cases\" | \"securitySolutionUI:alerts\" | \"securitySolutionUI:rules\" | \"securitySolutionUI:policy\" | \"securitySolutionUI:overview\" | \"securitySolutionUI:dashboards\" | \"securitySolutionUI:cases_create\" | \"securitySolutionUI:cases_configure\" | \"securitySolutionUI:hosts\" | \"securitySolutionUI:users\" | \"securitySolutionUI:cloud_defend-policies\" | \"securitySolutionUI:cloud_security_posture-dashboard\" | \"securitySolutionUI:cloud_security_posture-findings\" | \"securitySolutionUI:cloud_security_posture-benchmarks\" | \"securitySolutionUI:kubernetes\" | \"securitySolutionUI:network\" | \"securitySolutionUI:data_quality\" | \"securitySolutionUI:explore\" | \"securitySolutionUI:assets\" | \"securitySolutionUI:cloud_defend\" | \"securitySolutionUI:administration\" | \"securitySolutionUI:attack_discovery\" | \"securitySolutionUI:blocklist\" | \"securitySolutionUI:cloud_security_posture-rules\" | \"securitySolutionUI:detections\" | \"securitySolutionUI:detection_response\" | \"securitySolutionUI:endpoints\" | \"securitySolutionUI:event_filters\" | \"securitySolutionUI:exceptions\" | \"securitySolutionUI:host_isolation_exceptions\" | \"securitySolutionUI:hosts-all\" | \"securitySolutionUI:hosts-anomalies\" | \"securitySolutionUI:hosts-risk\" | \"securitySolutionUI:hosts-events\" | \"securitySolutionUI:hosts-sessions\" | \"securitySolutionUI:hosts-uncommon_processes\" | \"securitySolutionUI:investigations\" | \"securitySolutionUI:get_started\" | \"securitySolutionUI:machine_learning-landing\" | \"securitySolutionUI:network-anomalies\" | \"securitySolutionUI:network-dns\" | \"securitySolutionUI:network-events\" | \"securitySolutionUI:network-flows\" | \"securitySolutionUI:network-http\" | \"securitySolutionUI:network-tls\" | \"securitySolutionUI:response_actions_history\" | \"securitySolutionUI:rules-add\" | \"securitySolutionUI:rules-create\" | \"securitySolutionUI:rules-landing\" | \"securitySolutionUI:threat_intelligence\" | \"securitySolutionUI:timelines\" | \"securitySolutionUI:timelines-templates\" | \"securitySolutionUI:trusted_apps\" | \"securitySolutionUI:users-all\" | \"securitySolutionUI:users-anomalies\" | \"securitySolutionUI:users-authentications\" | \"securitySolutionUI:users-events\" | \"securitySolutionUI:users-risk\" | \"securitySolutionUI:entity_analytics\" | \"securitySolutionUI:entity_analytics-management\" | \"securitySolutionUI:entity_analytics-asset-classification\" | \"securitySolutionUI:coverage-overview\" | \"securitySolutionUI:notes-management\"" ], "path": "packages/deeplinks/security/index.ts", "deprecated": false, @@ -73,7 +73,7 @@ "label": "LinkId", "description": [], "signature": [ - "\"\" | \"cases\" | \"alerts\" | \"rules\" | \"policy\" | \"overview\" | \"dashboards\" | \"cases_create\" | \"cases_configure\" | \"hosts\" | \"users\" | \"cloud_defend-policies\" | \"cloud_security_posture-dashboard\" | \"cloud_security_posture-findings\" | \"cloud_security_posture-benchmarks\" | \"kubernetes\" | \"network\" | \"data_quality\" | \"explore\" | \"assets\" | \"cloud_defend\" | \"administration\" | \"attack_discovery\" | \"blocklist\" | \"cloud_security_posture-rules\" | \"detections\" | \"detection_response\" | \"endpoints\" | \"event_filters\" | \"exceptions\" | \"host_isolation_exceptions\" | \"hosts-all\" | \"hosts-anomalies\" | \"hosts-risk\" | \"hosts-events\" | \"hosts-sessions\" | \"hosts-uncommon_processes\" | \"investigations\" | \"get_started\" | \"machine_learning-landing\" | \"network-anomalies\" | \"network-dns\" | \"network-events\" | \"network-flows\" | \"network-http\" | \"network-tls\" | \"response_actions_history\" | \"rules-add\" | \"rules-create\" | \"rules-landing\" | \"threat_intelligence\" | \"timelines\" | \"timelines-templates\" | \"trusted_apps\" | \"users-all\" | \"users-anomalies\" | \"users-authentications\" | \"users-events\" | \"users-risk\" | \"entity_analytics\" | \"entity_analytics-management\" | \"entity_analytics-asset-classification\" | \"coverage-overview\"" + "\"\" | \"cases\" | \"alerts\" | \"rules\" | \"policy\" | \"overview\" | \"dashboards\" | \"cases_create\" | \"cases_configure\" | \"hosts\" | \"users\" | \"cloud_defend-policies\" | \"cloud_security_posture-dashboard\" | \"cloud_security_posture-findings\" | \"cloud_security_posture-benchmarks\" | \"kubernetes\" | \"network\" | \"data_quality\" | \"explore\" | \"assets\" | \"cloud_defend\" | \"administration\" | \"attack_discovery\" | \"blocklist\" | \"cloud_security_posture-rules\" | \"detections\" | \"detection_response\" | \"endpoints\" | \"event_filters\" | \"exceptions\" | \"host_isolation_exceptions\" | \"hosts-all\" | \"hosts-anomalies\" | \"hosts-risk\" | \"hosts-events\" | \"hosts-sessions\" | \"hosts-uncommon_processes\" | \"investigations\" | \"get_started\" | \"machine_learning-landing\" | \"network-anomalies\" | \"network-dns\" | \"network-events\" | \"network-flows\" | \"network-http\" | \"network-tls\" | \"response_actions_history\" | \"rules-add\" | \"rules-create\" | \"rules-landing\" | \"threat_intelligence\" | \"timelines\" | \"timelines-templates\" | \"trusted_apps\" | \"users-all\" | \"users-anomalies\" | \"users-authentications\" | \"users-events\" | \"users-risk\" | \"entity_analytics\" | \"entity_analytics-management\" | \"entity_analytics-asset-classification\" | \"coverage-overview\" | \"notes-management\"" ], "path": "packages/deeplinks/security/index.ts", "deprecated": false, diff --git a/api_docs/kbn_deeplinks_security.mdx b/api_docs/kbn_deeplinks_security.mdx index 3a0f870d4b335..1eb07631bd8ae 100644 --- a/api_docs/kbn_deeplinks_security.mdx +++ b/api_docs/kbn_deeplinks_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-security title: "@kbn/deeplinks-security" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-security plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-security'] --- import kbnDeeplinksSecurityObj from './kbn_deeplinks_security.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_shared.mdx b/api_docs/kbn_deeplinks_shared.mdx index f6f6ad56ad946..c79f2f054e5e6 100644 --- a/api_docs/kbn_deeplinks_shared.mdx +++ b/api_docs/kbn_deeplinks_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-shared title: "@kbn/deeplinks-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-shared plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-shared'] --- import kbnDeeplinksSharedObj from './kbn_deeplinks_shared.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index e14dddf6997f9..4cc118f0038c3 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 243fd8639335c..4e4c7a5e1cbbe 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index 8c800bbe4517e..752e3fdbd17ed 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index face43c46780e..0619209c5133d 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 1217a0ca13fa9..6dcc7055b3f00 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: 2024-06-18 +date: 2024-06-19 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 9d914ba9978e5..5382194ebec16 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: 2024-06-18 +date: 2024-06-19 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 c59ecdf80707b..99148ba4dc8fd 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: 2024-06-18 +date: 2024-06-19 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 4a501d42c4ebd..f5414936849fc 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.devdocs.json b/api_docs/kbn_discover_utils.devdocs.json index 641ea8ff21b2e..6777a3f093a66 100644 --- a/api_docs/kbn_discover_utils.devdocs.json +++ b/api_docs/kbn_discover_utils.devdocs.json @@ -279,6 +279,41 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.createLogsContextService", + "type": "Function", + "tags": [], + "label": "createLogsContextService", + "description": [], + "signature": [ + "(_deps?: ", + "LogsContextServiceDeps", + ") => { isLogsIndexPattern: (indexPattern: unknown) => boolean; }" + ], + "path": "packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.createLogsContextService.$1", + "type": "Object", + "tags": [], + "label": "_deps", + "description": [], + "signature": [ + "LogsContextServiceDeps" + ], + "path": "packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.formatFieldValue", @@ -1801,6 +1836,52 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.LogsContextService", + "type": "Interface", + "tags": [], + "label": "LogsContextService", + "description": [], + "path": "packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.LogsContextService.isLogsIndexPattern", + "type": "Function", + "tags": [], + "label": "isLogsIndexPattern", + "description": [], + "signature": [ + "(indexPattern: unknown) => boolean" + ], + "path": "packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.LogsContextService.isLogsIndexPattern.$1", + "type": "Unknown", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + "unknown" + ], + "path": "packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.LogStackTraceFields", @@ -1918,6 +1999,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.DEFAULT_ALLOWED_LOGS_BASE_PATTERNS", + "type": "Array", + "tags": [], + "label": "DEFAULT_ALLOWED_LOGS_BASE_PATTERNS", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-discover-utils/src/data_types/logs/logs_context_service.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.DEFAULT_COLUMNS_SETTING", diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index ff6d52f0aec76..100bd04b1e3aa 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 114 | 0 | 88 | 0 | +| 120 | 0 | 94 | 1 | ## Common diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 99b4070129b90..949b00b86eed2 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: 2024-06-18 +date: 2024-06-19 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 1c009ad6ae1fb..b709c1656cde5 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index ad520c4d0940d..20f8a3b4caecd 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt.devdocs.json b/api_docs/kbn_ebt.devdocs.json new file mode 100644 index 0000000000000..82e6770af4fac --- /dev/null +++ b/api_docs/kbn_ebt.devdocs.json @@ -0,0 +1,4130 @@ +{ + "id": "@kbn/ebt", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper", + "type": "Class", + "tags": [], + "label": "ElasticV3BrowserShipper", + "description": [ + "\nElastic V3 shipper to use in the browser." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ElasticV3BrowserShipper", + "text": "ElasticV3BrowserShipper" + }, + " implements ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.IShipper", + "text": "IShipper" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.shipperName", + "type": "string", + "tags": [], + "label": "shipperName", + "description": [ + "Shipper's unique name" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "Observable to emit the stats of the processed events." + ], + "signature": [ + "Subject", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + ">" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [ + "\nCreates a new instance of the {@link ElasticV3BrowserShipper}." + ], + "signature": [ + "any" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "{@link ElasticV3ShipperOptions }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ElasticV3ShipperOptions", + "text": "ElasticV3ShipperOptions" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "initContext", + "description": [ + "{@link AnalyticsClientInitContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AnalyticsClientInitContext", + "text": "AnalyticsClientInitContext" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.extendContext", + "type": "Function", + "tags": [], + "label": "extendContext", + "description": [ + "\nUses the `cluster_uuid` and `license_id` from the context to hold them in memory for the generation of the headers\nused later on in the HTTP request." + ], + "signature": [ + "(newContext: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + }, + ") => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.extendContext.$1", + "type": "Object", + "tags": [], + "label": "newContext", + "description": [ + "The full new context to set {@link EventContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nWhen `false`, it flushes the internal queue and stops sending events." + ], + "signature": [ + "(isOptedIn: boolean) => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.optIn.$1", + "type": "boolean", + "tags": [], + "label": "isOptedIn", + "description": [ + "`true` for resume sending events. `false` to stop." + ], + "signature": [ + "boolean" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.reportEvents", + "type": "Function", + "tags": [], + "label": "reportEvents", + "description": [ + "\nEnqueues the events to be sent to in a batched approach." + ], + "signature": [ + "(events: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]) => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.reportEvents.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [ + "batched events {@link Event }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nTriggers a flush of the internal queue to attempt to send any events held in the queue\nand resolves the returned promise once the queue is emptied." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3BrowserShipper.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nShuts down the shipper.\nTriggers a flush of the internal queue to attempt to send any events held in the queue." + ], + "signature": [ + "() => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/browser/src/browser_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper", + "type": "Class", + "tags": [], + "label": "ElasticV3ServerShipper", + "description": [ + "\nElastic V3 shipper to use on the server side." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ElasticV3ServerShipper", + "text": "ElasticV3ServerShipper" + }, + " implements ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.IShipper", + "text": "IShipper" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.shipperName", + "type": "string", + "tags": [], + "label": "shipperName", + "description": [ + "Shipper's unique name" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "Observable to emit the stats of the processed events." + ], + "signature": [ + "Subject", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + ">" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [ + "\nCreates a new instance of the {@link ElasticV3ServerShipper}." + ], + "signature": [ + "any" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "{@link ElasticV3ShipperOptions }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ElasticV3ShipperOptions", + "text": "ElasticV3ShipperOptions" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "initContext", + "description": [ + "{@link AnalyticsClientInitContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AnalyticsClientInitContext", + "text": "AnalyticsClientInitContext" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.extendContext", + "type": "Function", + "tags": [], + "label": "extendContext", + "description": [ + "\nUses the `cluster_uuid` and `license_id` from the context to hold them in memory for the generation of the headers\nused later on in the HTTP request." + ], + "signature": [ + "(newContext: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + }, + ") => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.extendContext.$1", + "type": "Object", + "tags": [], + "label": "newContext", + "description": [ + "The full new context to set {@link EventContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nWhen `false`, it flushes the internal queue and stops sending events." + ], + "signature": [ + "(isOptedIn: boolean) => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.optIn.$1", + "type": "boolean", + "tags": [], + "label": "isOptedIn", + "description": [ + "`true` for resume sending events. `false` to stop." + ], + "signature": [ + "boolean" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.reportEvents", + "type": "Function", + "tags": [], + "label": "reportEvents", + "description": [ + "\nEnqueues the events to be sent via the leaky bucket algorithm." + ], + "signature": [ + "(events: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]) => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.reportEvents.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [ + "batched events {@link Event }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nTriggers a flush of the internal queue to attempt to send any events held in the queue\nand resolves the returned promise once the queue is emptied." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ServerShipper.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nShuts down the shipper.\nTriggers a flush of the internal queue to attempt to send any events held in the queue." + ], + "signature": [ + "() => void" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/server/src/server_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper", + "type": "Class", + "tags": [], + "label": "FullStoryShipper", + "description": [ + "\nFullStory shipper." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.FullStoryShipper", + "text": "FullStoryShipper" + }, + " implements ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.IShipper", + "text": "IShipper" + } + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.shipperName", + "type": "string", + "tags": [], + "label": "shipperName", + "description": [ + "Shipper's unique name" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [ + "\nCreates a new instance of the FullStoryShipper." + ], + "signature": [ + "any" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [ + "{@link FullStoryShipperConfig }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.FullStoryShipperConfig", + "text": "FullStoryShipperConfig" + } + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "initContext", + "description": [ + "{@link AnalyticsClientInitContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AnalyticsClientInitContext", + "text": "AnalyticsClientInitContext" + } + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.extendContext", + "type": "Function", + "tags": [], + "label": "extendContext", + "description": [ + "\nCalls `fs.identify`, `fs.setUserVars` and `fs.setVars` depending on the fields provided in the newContext." + ], + "signature": [ + "(newContext: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + }, + ") => void" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.extendContext.$1", + "type": "Object", + "tags": [], + "label": "newContext", + "description": [ + "The full new context to set {@link EventContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nStops/restarts the shipping mechanism based on the value of isOptedIn" + ], + "signature": [ + "(isOptedIn: boolean) => void" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.optIn.$1", + "type": "boolean", + "tags": [], + "label": "isOptedIn", + "description": [ + "`true` for resume sending events. `false` to stop." + ], + "signature": [ + "boolean" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.reportEvents", + "type": "Function", + "tags": [], + "label": "reportEvents", + "description": [ + "\nFilters the events by the eventTypesAllowlist from the config.\nThen it transforms the event into a FS valid format and calls `fs.event`." + ], + "signature": [ + "(events: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]) => void" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.reportEvents.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [ + "batched events {@link Event }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nFlushes all internal queues of the shipper.\nIt doesn't really do anything inside because this shipper doesn't hold any internal queues." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipper.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nShuts down the shipper." + ], + "signature": [ + "() => void" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AnalyticsClientInitContext", + "type": "Interface", + "tags": [], + "label": "AnalyticsClientInitContext", + "description": [ + "\nGeneral settings of the analytics client" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AnalyticsClientInitContext.isDev", + "type": "boolean", + "tags": [], + "label": "isDev", + "description": [ + "\nBoolean indicating if it's running in developer mode." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AnalyticsClientInitContext.sendTo", + "type": "CompoundType", + "tags": [], + "label": "sendTo", + "description": [ + "\nSpecify if the shippers should send their data to the production or staging environments." + ], + "signature": [ + "\"production\" | \"staging\"" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AnalyticsClientInitContext.logger", + "type": "Object", + "tags": [], + "label": "logger", + "description": [ + "\nApplication-provided logger." + ], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ContextProviderOpts", + "type": "Interface", + "tags": [], + "label": "ContextProviderOpts", + "description": [ + "\nDefinition of a context provider" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ContextProviderOpts.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nThe name of the provider." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ContextProviderOpts.context$", + "type": "Object", + "tags": [], + "label": "context$", + "description": [ + "\nObservable that emits the custom context." + ], + "signature": [ + "Observable", + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ContextProviderOpts.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [ + "\nSchema declaring and documenting the expected output in the context$\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ShipperOptions", + "type": "Interface", + "tags": [], + "label": "ElasticV3ShipperOptions", + "description": [ + "\nOptions for the Elastic V3 shipper" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ShipperOptions.channelName", + "type": "string", + "tags": [], + "label": "channelName", + "description": [ + "\nThe name of the channel to stream all the events to." + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ShipperOptions.version", + "type": "string", + "tags": [], + "label": "version", + "description": [ + "\nThe product's version." + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ShipperOptions.sendTo", + "type": "CompoundType", + "tags": [], + "label": "sendTo", + "description": [ + "\nProvide it to override the Analytics client's default configuration." + ], + "signature": [ + "\"production\" | \"staging\" | undefined" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ElasticV3ShipperOptions.debug", + "type": "CompoundType", + "tags": [], + "label": "debug", + "description": [ + "\nShould show debug information about the requests it makes to the V3 API." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/analytics/ebt/shippers/elastic_v3/common/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.Event", + "type": "Interface", + "tags": [], + "label": "Event", + "description": [ + "\nDefinition of the full event structure" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.Event.timestamp", + "type": "string", + "tags": [], + "label": "timestamp", + "description": [ + "\nThe time the event was generated in ISO format." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.Event.event_type", + "type": "string", + "tags": [], + "label": "event_type", + "description": [ + "\nThe event type." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.Event.properties", + "type": "Uncategorized", + "tags": [], + "label": "properties", + "description": [ + "\nThe specific properties of the event type." + ], + "signature": [ + "Properties" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.Event.context", + "type": "Object", + "tags": [], + "label": "context", + "description": [ + "\nThe {@link EventContext} enriched during the processing pipeline." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext", + "type": "Interface", + "tags": [], + "label": "EventContext", + "description": [ + "\nDefinition of the context that can be appended to the events through the {@link IAnalyticsClient.registerContextProvider}." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.cluster_uuid", + "type": "string", + "tags": [], + "label": "cluster_uuid", + "description": [ + "\nThe UUID of the cluster" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.cluster_name", + "type": "string", + "tags": [], + "label": "cluster_name", + "description": [ + "\nThe name of the cluster." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.license_id", + "type": "string", + "tags": [], + "label": "license_id", + "description": [ + "\nThe license ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.userId", + "type": "string", + "tags": [], + "label": "userId", + "description": [ + "\nThe unique user ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.cloudId", + "type": "string", + "tags": [], + "label": "cloudId", + "description": [ + "\nThe Cloud ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.isElasticCloudUser", + "type": "CompoundType", + "tags": [], + "label": "isElasticCloudUser", + "description": [ + "\n`true` if the user is logged in via the Elastic Cloud authentication provider." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.version", + "type": "string", + "tags": [], + "label": "version", + "description": [ + "\nThe product's version." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.pageName", + "type": "string", + "tags": [], + "label": "pageName", + "description": [ + "\nThe name of the current page." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.applicationId", + "type": "string", + "tags": [], + "label": "applicationId", + "description": [ + "\nThe current application ID." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.entityId", + "type": "string", + "tags": [], + "label": "entityId", + "description": [ + "\nThe current entity ID (dashboard ID, visualization ID, etc.)." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventContext.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[key: string]: unknown", + "description": [ + "\nAdditional keys are allowed." + ], + "signature": [ + "[key: string]: unknown" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventTypeOpts", + "type": "Interface", + "tags": [], + "label": "EventTypeOpts", + "description": [ + "\nDefinition of an Event Type." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventTypeOpts.eventType", + "type": "string", + "tags": [], + "label": "eventType", + "description": [ + "\nThe event type's unique name." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventTypeOpts.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [ + "\nSchema declaring and documenting the expected structure of this event type.\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipperConfig", + "type": "Interface", + "tags": [], + "label": "FullStoryShipperConfig", + "description": [ + "\nFullStory shipper configuration." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.FullStoryShipperConfig", + "text": "FullStoryShipperConfig" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.FullStorySnippetConfig", + "text": "FullStorySnippetConfig" + } + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipperConfig.eventTypesAllowlist", + "type": "Array", + "tags": [], + "label": "eventTypesAllowlist", + "description": [ + "\nFullStory's custom events rate limit is very aggressive.\nIf this setting is provided, it'll only send the event types specified in this list." + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStoryShipperConfig.pageVarsDebounceTimeMs", + "type": "number", + "tags": [], + "label": "pageVarsDebounceTimeMs", + "description": [ + "\nFullStory only allows calling setVars('page') once per navigation.\nThis setting defines how much time to hold from calling the API while additional lazy context is being resolved." + ], + "signature": [ + "number | undefined" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/fullstory_shipper.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStorySnippetConfig", + "type": "Interface", + "tags": [], + "label": "FullStorySnippetConfig", + "description": [ + "\nFullStory basic configuration." + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStorySnippetConfig.fullStoryOrgId", + "type": "string", + "tags": [], + "label": "fullStoryOrgId", + "description": [ + "\nThe FullStory account id." + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStorySnippetConfig.host", + "type": "string", + "tags": [], + "label": "host", + "description": [ + "\nThe host to send the data to. Used to overcome AdBlockers by using custom DNSs.\nIf not specified, it defaults to `fullstory.com`." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStorySnippetConfig.scriptUrl", + "type": "string", + "tags": [], + "label": "scriptUrl", + "description": [ + "\nThe URL to load the FullStory client from. Falls back to `edge.fullstory.com/s/fs.js` if not specified." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStorySnippetConfig.debug", + "type": "CompoundType", + "tags": [], + "label": "debug", + "description": [ + "\nWhether the debug logs should be printed to the console." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.FullStorySnippetConfig.namespace", + "type": "string", + "tags": [], + "label": "namespace", + "description": [ + "\nThe name of the variable where the API is stored: `window[namespace]`. Defaults to `FS`." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/analytics/ebt/shippers/fullstory/src/load_snippet.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient", + "type": "Interface", + "tags": [], + "label": "IAnalyticsClient", + "description": [ + "\nAnalytics client's public APIs" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.reportEvent", + "type": "Function", + "tags": [ + "track-adoption" + ], + "label": "reportEvent", + "description": [ + "\nReports a telemetry event." + ], + "signature": [ + "(eventType: string, eventData: EventTypeData) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "@kbn/core-notifications-browser-internal", + "path": "packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_reporter.ts" + }, + { + "plugin": "@kbn/core-notifications-browser-internal", + "path": "packages/core/notifications/core-notifications-browser-internal/src/toasts/telemetry/event_reporter.ts" + }, + { + "plugin": "@kbn/ebt-tools", + "path": "packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-server-internal", + "path": "packages/core/root/core-root-server-internal/src/events/kibana_started.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "@kbn/cloud", + "path": "packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/types.ts" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/analytics_service.ts" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/server/utils/recall/recall_and_score.ts" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/analytics/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" + }, + { + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + }, + { + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/usage/event_tracker.ts" + }, + { + "plugin": "searchPlayground", + "path": "x-pack/plugins/search_playground/server/routes.ts" + }, + { + "plugin": "securitySolutionServerless", + "path": "x-pack/plugins/security_solution_serverless/server/task_manager/nlp_cleanup_task/nlp_cleanup_task.ts" + }, + { + "plugin": "securitySolutionServerless", + "path": "x-pack/plugins/security_solution_serverless/server/task_manager/nlp_cleanup_task/nlp_cleanup_task.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_client.ts" + }, + { + "plugin": "observabilityLogsExplorer", + "path": "x-pack/plugins/observability_solution/observability_logs_explorer/public/state_machines/observability_logs_explorer/src/telemetry_events.ts" + }, + { + "plugin": "observabilityOnboarding", + "path": "x-pack/plugins/observability_solution/observability_onboarding/public/hooks/use_flow_progress_telemetry.ts" + }, + { + "plugin": "observabilityOnboarding", + "path": "x-pack/plugins/observability_solution/observability_onboarding/public/application/app.tsx" + }, + { + "plugin": "observabilityAIAssistant", + "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "dashboard", + "path": "src/plugins/dashboard/public/services/analytics/analytics.stub.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.reportEvent.$1", + "type": "string", + "tags": [], + "label": "eventType", + "description": [ + "The event type registered via the `registerEventType` API." + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.reportEvent.$2", + "type": "Uncategorized", + "tags": [], + "label": "eventData", + "description": [ + "The properties matching the schema declared in the `registerEventType` API." + ], + "signature": [ + "EventTypeData" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerEventType", + "type": "Function", + "tags": [], + "label": "registerEventType", + "description": [ + "\nRegisters the event type that will be emitted via the reportEvent API." + ], + "signature": [ + "(eventTypeOps: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerEventType.$1", + "type": "Object", + "tags": [], + "label": "eventTypeOps", + "description": [ + "The definition of the event type {@link EventTypeOpts }." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventTypeOpts", + "text": "EventTypeOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerShipper", + "type": "Function", + "tags": [], + "label": "registerShipper", + "description": [ + "\nSet up the shipper that will be used to report the telemetry events." + ], + "signature": [ + "(Shipper: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + ", shipperConfig: ShipperConfig, opts?: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.RegisterShipperOpts", + "text": "RegisterShipperOpts" + }, + " | undefined) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerShipper.$1", + "type": "Object", + "tags": [], + "label": "Shipper", + "description": [ + "The {@link IShipper } class to instantiate the shipper." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerShipper.$2", + "type": "Uncategorized", + "tags": [], + "label": "shipperConfig", + "description": [ + "The config specific to the Shipper to instantiate." + ], + "signature": [ + "ShipperConfig" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerShipper.$3", + "type": "Object", + "tags": [], + "label": "opts", + "description": [ + "Additional options to register the shipper {@link RegisterShipperOpts }." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.RegisterShipperOpts", + "text": "RegisterShipperOpts" + }, + " | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nUsed to control the user's consent to report the data.\nIn the advanced mode, it allows to \"cherry-pick\" which events and shippers are enabled/disabled." + ], + "signature": [ + "(optInConfig: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfig", + "text": "OptInConfig" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.optIn.$1", + "type": "Object", + "tags": [], + "label": "optInConfig", + "description": [ + "{@link OptInConfig }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfig", + "text": "OptInConfig" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerContextProvider", + "type": "Function", + "tags": [ + "track-adoption" + ], + "label": "registerContextProvider", + "description": [ + "\nRegisters the context provider to enrich any reported events." + ], + "signature": [ + "(contextProviderOpts: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + ") => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": true, + "references": [ + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-elasticsearch-server-internal", + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts" + }, + { + "plugin": "@kbn/core-environment-server-internal", + "path": "packages/core/environment/core-environment-server-internal/src/environment_service.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-plugins-server-internal", + "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts" + }, + { + "plugin": "licensing", + "path": "x-pack/plugins/licensing/common/register_analytics_context_provider.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/plugin.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/plugin.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-mocks", + "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-application-browser-internal", + "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.test.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-analytics-server-mocks", + "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" + }, + { + "plugin": "@kbn/core-elasticsearch-server-internal", + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.mocks.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.ts" + }, + { + "plugin": "@kbn/core-analytics-server-internal", + "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.test.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.registerContextProvider.$1", + "type": "Object", + "tags": [], + "label": "contextProviderOpts", + "description": [ + "{@link ContextProviderOpts }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ContextProviderOpts", + "text": "ContextProviderOpts" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.removeContextProvider", + "type": "Function", + "tags": [], + "label": "removeContextProvider", + "description": [ + "\nRemoves the context provider and stop enriching the events from its context." + ], + "signature": [ + "(contextProviderName: string) => void" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.removeContextProvider.$1", + "type": "string", + "tags": [], + "label": "contextProviderName", + "description": [ + "The name of the context provider to remove." + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "\nObservable to emit the stats of the processed events." + ], + "signature": [ + "Observable", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + ">" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nForces all shippers to send all their enqueued events and fulfills the returned promise." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IAnalyticsClient.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nStops the client. Flushing any pending events in the process." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper", + "type": "Interface", + "tags": [], + "label": "IShipper", + "description": [ + "\nBasic structure of a Shipper" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.reportEvents", + "type": "Function", + "tags": [], + "label": "reportEvents", + "description": [ + "\nAdapts and ships the event to the persisting/analytics solution." + ], + "signature": [ + "(events: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]) => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.reportEvents.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [ + "batched events {@link Event }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.Event", + "text": "Event" + }, + ">[]" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.optIn", + "type": "Function", + "tags": [], + "label": "optIn", + "description": [ + "\nStops/restarts the shipping mechanism based on the value of isOptedIn" + ], + "signature": [ + "(isOptedIn: boolean) => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.optIn.$1", + "type": "boolean", + "tags": [], + "label": "isOptedIn", + "description": [ + "`true` for resume sending events. `false` to stop." + ], + "signature": [ + "boolean" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.extendContext", + "type": "Function", + "tags": [], + "label": "extendContext", + "description": [ + "\nPerform any necessary calls to the persisting/analytics solution to set the event's context." + ], + "signature": [ + "((newContext: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + }, + ") => void) | undefined" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.extendContext.$1", + "type": "Object", + "tags": [], + "label": "newContext", + "description": [ + "The full new context to set {@link EventContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.EventContext", + "text": "EventContext" + } + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.telemetryCounter$", + "type": "Object", + "tags": [], + "label": "telemetryCounter$", + "description": [ + "\nObservable to emit the stats of the processed events." + ], + "signature": [ + "Observable", + "<", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.TelemetryCounter", + "text": "TelemetryCounter" + }, + "> | undefined" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.flush", + "type": "Function", + "tags": [], + "label": "flush", + "description": [ + "\nSends all the enqueued events and fulfills the returned promise." + ], + "signature": [ + "() => Promise" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.IShipper.shutdown", + "type": "Function", + "tags": [], + "label": "shutdown", + "description": [ + "\nShutdown the shipper." + ], + "signature": [ + "() => void" + ], + "path": "packages/analytics/ebt/client/src/shippers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.OptInConfig", + "type": "Interface", + "tags": [], + "label": "OptInConfig", + "description": [ + "\nOptions for the optIn API" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.OptInConfig.global", + "type": "Object", + "tags": [], + "label": "global", + "description": [ + "\nControls the global enabled/disabled behaviour of the client and shippers." + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.OptInConfigPerType", + "text": "OptInConfigPerType" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.OptInConfig.event_types", + "type": "Object", + "tags": [], + "label": "event_types", + "description": [ + "\nControls if an event type should be disabled for a specific type of shipper." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.OptInConfigPerType", + "type": "Interface", + "tags": [], + "label": "OptInConfigPerType", + "description": [ + "\nSets whether a type of event is enabled/disabled globally or per shipper." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.OptInConfigPerType.enabled", + "type": "boolean", + "tags": [], + "label": "enabled", + "description": [ + "\nThe event type is globally enabled." + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.OptInConfigPerType.shippers", + "type": "Object", + "tags": [], + "label": "shippers", + "description": [ + "\nControls if an event type should be disabled for a specific type of shipper." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.RegisterShipperOpts", + "type": "Interface", + "tags": [], + "label": "RegisterShipperOpts", + "description": [ + "\nOptional options to register a shipper" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaArray", + "type": "Interface", + "tags": [], + "label": "SchemaArray", + "description": [ + "\nSchema to represent an array" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaArray.type", + "type": "string", + "tags": [], + "label": "type", + "description": [ + "The type must be an array" + ], + "signature": [ + "\"array\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaArray.items", + "type": "CompoundType", + "tags": [], + "label": "items", + "description": [ + "The schema of the items in the array is defined in the `items` property" + ], + "signature": [ + "{ type: \"pass_through\"; _meta: { description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "; } | (unknown extends Value ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends (infer U)[] | readonly (infer U)[] ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " : NonNullable extends Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends object ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + ")" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaChildValue", + "type": "Interface", + "tags": [], + "label": "SchemaChildValue", + "description": [ + "\nSchema to define a primitive value" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaChildValue.type", + "type": "Uncategorized", + "tags": [], + "label": "type", + "description": [ + "The type of the value" + ], + "signature": [ + "NonNullable extends string | Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaStringTypes", + "text": "AllowedSchemaStringTypes" + }, + " : NonNullable extends number ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaNumberTypes", + "text": "AllowedSchemaNumberTypes" + }, + " : NonNullable extends boolean ? \"boolean\" : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaTypes", + "text": "AllowedSchemaTypes" + } + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaChildValue._meta", + "type": "CompoundType", + "tags": [], + "label": "_meta", + "description": [ + "Meta properties of the value: description and is optional" + ], + "signature": [ + "{ description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaMeta", + "type": "Interface", + "tags": [], + "label": "SchemaMeta", + "description": [ + "\nSchema meta with optional description" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaMeta._meta", + "type": "CompoundType", + "tags": [], + "label": "_meta", + "description": [ + "Meta properties of the pass through: description and is optional" + ], + "signature": [ + "({ description?: string | undefined; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + ") | undefined" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaObject", + "type": "Interface", + "tags": [], + "label": "SchemaObject", + "description": [ + "\nSchema to represent an object" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " extends ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMeta", + "text": "SchemaMeta" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaObject.properties", + "type": "Object", + "tags": [], + "label": "properties", + "description": [ + "\nThe schemas of the keys of the object are defined in the `properties` object." + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ShipperClassConstructor", + "type": "Interface", + "tags": [], + "label": "ShipperClassConstructor", + "description": [ + "\nConstructor of a {@link IShipper}" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.ShipperClassConstructor", + "text": "ShipperClassConstructor" + }, + "" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ShipperClassConstructor.shipperName", + "type": "string", + "tags": [], + "label": "shipperName", + "description": [ + "\nThe shipper's unique name" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ShipperClassConstructor.new", + "type": "Function", + "tags": [], + "label": "new", + "description": [ + "\nThe constructor" + ], + "signature": [ + "any" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ShipperClassConstructor.new.$1", + "type": "Uncategorized", + "tags": [], + "label": "config", + "description": [ + "The shipper's custom config" + ], + "signature": [ + "Config" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ShipperClassConstructor.new.$2", + "type": "Object", + "tags": [], + "label": "initContext", + "description": [ + "Common context {@link AnalyticsClientInitContext }" + ], + "signature": [ + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AnalyticsClientInitContext", + "text": "AnalyticsClientInitContext" + } + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounter", + "type": "Interface", + "tags": [], + "label": "TelemetryCounter", + "description": [ + "\nShape of the events emitted by the telemetryCounter$ observable" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounter.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [ + "\n{@link TelemetryCounterType}" + ], + "signature": [ + "\"succeeded\" | \"failed\" | \"enqueued\" | \"sent_to_shipper\" | \"dropped\"" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounter.source", + "type": "string", + "tags": [], + "label": "source", + "description": [ + "\nWho emitted the event? It can be \"client\" or the name of the shipper." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounter.event_type", + "type": "string", + "tags": [], + "label": "event_type", + "description": [ + "\nThe event type the success/failure/drop event refers to." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounter.code", + "type": "string", + "tags": [], + "label": "code", + "description": [ + "\nCode to provide additional information about the success or failure. Examples are 200/400/504/ValidationError/UnknownError" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounter.count", + "type": "number", + "tags": [], + "label": "count", + "description": [ + "\nThe number of events that this counter refers to." + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AllowedSchemaBooleanTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaBooleanTypes", + "description": [ + "Types matching boolean values" + ], + "signature": [ + "\"boolean\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AllowedSchemaNumberTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaNumberTypes", + "description": [ + "Types matching number values" + ], + "signature": [ + "\"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AllowedSchemaStringTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaStringTypes", + "description": [ + "Types matching string values" + ], + "signature": [ + "\"keyword\" | \"text\" | \"date\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.AllowedSchemaTypes", + "type": "Type", + "tags": [], + "label": "AllowedSchemaTypes", + "description": [ + "\nPossible type values in the schema" + ], + "signature": [ + "\"boolean\" | \"keyword\" | \"text\" | \"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ContextProviderName", + "type": "Type", + "tags": [], + "label": "ContextProviderName", + "description": [ + "\nContextProviderName used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.EventType", + "type": "Type", + "tags": [], + "label": "EventType", + "description": [ + "\nEvent Type used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.PossibleSchemaTypes", + "type": "Type", + "tags": [], + "label": "PossibleSchemaTypes", + "description": [ + "\nHelper to ensure the declared types match the schema types" + ], + "signature": [ + "Value extends string | Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaStringTypes", + "text": "AllowedSchemaStringTypes" + }, + " : Value extends number ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaNumberTypes", + "text": "AllowedSchemaNumberTypes" + }, + " : Value extends boolean ? \"boolean\" : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.AllowedSchemaTypes", + "text": "AllowedSchemaTypes" + } + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.RootSchema", + "type": "Type", + "tags": [], + "label": "RootSchema", + "description": [ + "\nSchema definition to match the structure of the properties provided.\n" + ], + "signature": [ + "{ [Key in keyof Required]: ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaValue", + "text": "SchemaValue" + }, + "; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaMetaOptional", + "type": "Type", + "tags": [], + "label": "SchemaMetaOptional", + "description": [ + "\nEnforces { optional: true } if the value can be undefined" + ], + "signature": [ + "unknown extends Value ? { optional?: boolean | undefined; } : undefined extends Value ? { optional: true; } : { optional?: false | undefined; }" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.SchemaValue", + "type": "Type", + "tags": [], + "label": "SchemaValue", + "description": [ + "\nType that defines all the possible values that the Schema accepts.\nThese types definitions are helping to identify earlier the possible missing `properties` nesting when\nmanually defining the schemas." + ], + "signature": [ + "{ type: \"pass_through\"; _meta: { description: string; } & ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaMetaOptional", + "text": "SchemaMetaOptional" + }, + "; } | (unknown extends Value ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " | ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends (infer U)[] | readonly (infer U)[] ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaArray", + "text": "SchemaArray" + }, + " : NonNullable extends Date ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + " : NonNullable extends object ? ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaObject", + "text": "SchemaObject" + }, + " : ", + { + "pluginId": "@kbn/ebt", + "scope": "common", + "docId": "kibKbnEbtPluginApi", + "section": "def-common.SchemaChildValue", + "text": "SchemaChildValue" + }, + ")" + ], + "path": "packages/analytics/ebt/client/src/schema/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.ShipperName", + "type": "Type", + "tags": [], + "label": "ShipperName", + "description": [ + "\nShipper Name used for indexed structures. Only used to improve the readability of the types" + ], + "signature": [ + "string" + ], + "path": "packages/analytics/ebt/client/src/analytics_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ebt", + "id": "def-common.TelemetryCounterType", + "type": "Type", + "tags": [], + "label": "TelemetryCounterType", + "description": [ + "\nIndicates if the event contains data about succeeded, failed or dropped events:\n- enqueued: The event was accepted and will be sent to the shippers when they become available (and opt-in === true).\n- sent_to_shipper: The event was sent to at least one shipper.\n- succeeded: The event was successfully sent by the shipper.\n- failed: There was an error when processing/shipping the event. Refer to the Telemetry Counter's code for the reason.\n- dropped: The event was dropped from the queue. Refer to the Telemetry Counter's code for the reason." + ], + "signature": [ + "\"succeeded\" | \"failed\" | \"enqueued\" | \"sent_to_shipper\" | \"dropped\"" + ], + "path": "packages/analytics/ebt/client/src/events/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_ebt.mdx b/api_docs/kbn_ebt.mdx new file mode 100644 index 0000000000000..eff48712195b2 --- /dev/null +++ b/api_docs/kbn_ebt.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnEbtPluginApi +slug: /kibana-dev-docs/api/kbn-ebt +title: "@kbn/ebt" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/ebt plugin +date: 2024-06-19 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt'] +--- +import kbnEbtObj from './kbn_ebt.devdocs.json'; + + + +Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 152 | 0 | 0 | 0 | + +## Common + +### Classes + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_ebt_tools.devdocs.json b/api_docs/kbn_ebt_tools.devdocs.json index ed143ac7aeec1..44363fefececf 100644 --- a/api_docs/kbn_ebt_tools.devdocs.json +++ b/api_docs/kbn_ebt_tools.devdocs.json @@ -65,9 +65,9 @@ "signature": [ "(analytics: Pick<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.IAnalyticsClient", "text": "IAnalyticsClient" }, @@ -89,9 +89,9 @@ "signature": [ "Pick<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.IAnalyticsClient", "text": "IAnalyticsClient" }, @@ -118,9 +118,9 @@ "signature": [ "(analytics: Pick<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.IAnalyticsClient", "text": "IAnalyticsClient" }, @@ -150,9 +150,9 @@ "signature": [ "Pick<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.IAnalyticsClient", "text": "IAnalyticsClient" }, diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index ef632ce1a693c..ecb6ea6043d71 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 6d0bfdecc3214..3966867b26154 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: 2024-06-18 +date: 2024-06-19 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_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index 389bd6dfbcb13..bc3aade98a916 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 822df19b8e86f..376443426f3db 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.devdocs.json b/api_docs/kbn_elastic_assistant_common.devdocs.json index 99c152889d5a3..7f5b1cccc8780 100644 --- a/api_docs/kbn_elastic_assistant_common.devdocs.json +++ b/api_docs/kbn_elastic_assistant_common.devdocs.json @@ -1607,6 +1607,18 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND", + "type": "string", + "tags": [], + "label": "ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_ENTRIES_URL_FIND", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.ELASTIC_AI_ASSISTANT_KNOWLEDGE_BASE_URL", @@ -1880,6 +1892,81 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesRequestQuery", + "type": "Type", + "tags": [], + "label": "FindKnowledgeBaseEntriesRequestQuery", + "description": [], + "signature": [ + "{ per_page: number; page: number; fields?: string[] | undefined; filter?: string | undefined; sort_field?: \"title\" | \"updated_at\" | \"created_at\" | \"is_default\" | undefined; sort_order?: \"asc\" | \"desc\" | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesRequestQueryInput", + "type": "Type", + "tags": [], + "label": "FindKnowledgeBaseEntriesRequestQueryInput", + "description": [], + "signature": [ + "{ fields?: unknown; filter?: string | undefined; sort_field?: \"title\" | \"updated_at\" | \"created_at\" | \"is_default\" | undefined; sort_order?: \"asc\" | \"desc\" | undefined; page?: number | undefined; per_page?: number | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesResponse", + "type": "Type", + "tags": [], + "label": "FindKnowledgeBaseEntriesResponse", + "description": [], + "signature": [ + "{ page: number; perPage: number; total: number; data: { id: string; namespace: string; text: string; createdAt: string; users: { id?: string | undefined; name?: string | undefined; }[]; timestamp?: string | undefined; createdBy?: string | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; metadata?: { source: string; required: boolean; kbResource: string; } | undefined; vector?: { modelId: string; tokens: {} & { [k: string]: number; }; } | undefined; }[]; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesSortField", + "type": "Type", + "tags": [], + "label": "FindKnowledgeBaseEntriesSortField", + "description": [], + "signature": [ + "\"title\" | \"updated_at\" | \"created_at\" | \"is_default\"" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesSortFieldEnum", + "type": "Type", + "tags": [], + "label": "FindKnowledgeBaseEntriesSortFieldEnum", + "description": [], + "signature": [ + "{ title: \"title\"; updated_at: \"updated_at\"; created_at: \"created_at\"; is_default: \"is_default\"; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.GetCapabilitiesResponse", @@ -2639,7 +2726,7 @@ "signature": [ "\"asc\" | \"desc\"" ], - "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts", + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -2654,7 +2741,7 @@ "signature": [ "{ asc: \"asc\"; desc: \"desc\"; }" ], - "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts", + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -3663,6 +3750,66 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesRequestQuery", + "type": "Object", + "tags": [], + "label": "FindKnowledgeBaseEntriesRequestQuery", + "description": [], + "signature": [ + "Zod.ZodObject<{ fields: Zod.ZodOptional, string[], unknown>>; filter: Zod.ZodOptional; sort_field: Zod.ZodOptional>; sort_order: Zod.ZodOptional>; page: Zod.ZodDefault>; per_page: Zod.ZodDefault>; }, \"strip\", Zod.ZodTypeAny, { per_page: number; page: number; fields?: string[] | undefined; filter?: string | undefined; sort_field?: \"title\" | \"updated_at\" | \"created_at\" | \"is_default\" | undefined; sort_order?: \"asc\" | \"desc\" | undefined; }, { fields?: unknown; filter?: string | undefined; sort_field?: \"title\" | \"updated_at\" | \"created_at\" | \"is_default\" | undefined; sort_order?: \"asc\" | \"desc\" | undefined; page?: number | undefined; per_page?: number | undefined; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesResponse", + "type": "Object", + "tags": [], + "label": "FindKnowledgeBaseEntriesResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ page: Zod.ZodNumber; perPage: Zod.ZodNumber; total: Zod.ZodNumber; data: Zod.ZodArray; id: Zod.ZodString; createdAt: Zod.ZodString; createdBy: Zod.ZodOptional; updatedAt: Zod.ZodOptional; updatedBy: Zod.ZodOptional; users: Zod.ZodArray; name: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { id?: string | undefined; name?: string | undefined; }, { id?: string | undefined; name?: string | undefined; }>, \"many\">; metadata: Zod.ZodOptional>; namespace: Zod.ZodString; text: Zod.ZodString; vector: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodNumber, \"strip\">>; }, \"strip\", Zod.ZodTypeAny, { modelId: string; tokens: {} & { [k: string]: number; }; }, { modelId: string; tokens: {} & { [k: string]: number; }; }>>; }, \"strip\", Zod.ZodTypeAny, { id: string; namespace: string; text: string; createdAt: string; users: { id?: string | undefined; name?: string | undefined; }[]; timestamp?: string | undefined; createdBy?: string | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; metadata?: { source: string; required: boolean; kbResource: string; } | undefined; vector?: { modelId: string; tokens: {} & { [k: string]: number; }; } | undefined; }, { id: string; namespace: string; text: string; createdAt: string; users: { id?: string | undefined; name?: string | undefined; }[]; timestamp?: string | undefined; createdBy?: string | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; metadata?: { source: string; required: boolean; kbResource: string; } | undefined; vector?: { modelId: string; tokens: {} & { [k: string]: number; }; } | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { page: number; perPage: number; total: number; data: { id: string; namespace: string; text: string; createdAt: string; users: { id?: string | undefined; name?: string | undefined; }[]; timestamp?: string | undefined; createdBy?: string | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; metadata?: { source: string; required: boolean; kbResource: string; } | undefined; vector?: { modelId: string; tokens: {} & { [k: string]: number; }; } | undefined; }[]; }, { page: number; perPage: number; total: number; data: { id: string; namespace: string; text: string; createdAt: string; users: { id?: string | undefined; name?: string | undefined; }[]; timestamp?: string | undefined; createdBy?: string | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; metadata?: { source: string; required: boolean; kbResource: string; } | undefined; vector?: { modelId: string; tokens: {} & { [k: string]: number; }; } | undefined; }[]; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesSortField", + "type": "Object", + "tags": [], + "label": "FindKnowledgeBaseEntriesSortField", + "description": [], + "signature": [ + "Zod.ZodEnum<[\"created_at\", \"is_default\", \"title\", \"updated_at\"]>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.FindKnowledgeBaseEntriesSortFieldEnum", + "type": "Object", + "tags": [], + "label": "FindKnowledgeBaseEntriesSortFieldEnum", + "description": [], + "signature": [ + "{ title: \"title\"; updated_at: \"updated_at\"; created_at: \"created_at\"; is_default: \"is_default\"; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/knowledge_base/find_knowledge_base_entries_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.GetCapabilitiesResponse", @@ -4273,7 +4420,7 @@ "signature": [ "Zod.ZodEnum<[\"asc\", \"desc\"]>" ], - "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts", + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -4288,7 +4435,7 @@ "signature": [ "{ asc: \"asc\"; desc: \"desc\"; }" ], - "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/find_conversations_route.gen.ts", + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/common_attributes.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index 9e4c31025175d..8c2dc5cdf2b7c 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 295 | 0 | 276 | 0 | +| 305 | 0 | 286 | 0 | ## Common diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index 198cfcc01bac4..68ab25caaed79 100644 --- a/api_docs/kbn_entities_schema.mdx +++ b/api_docs/kbn_entities_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-entities-schema title: "@kbn/entities-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/entities-schema plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/entities-schema'] --- import kbnEntitiesSchemaObj from './kbn_entities_schema.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 34e7553026526..1065242e2ce20 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: 2024-06-18 +date: 2024-06-19 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 fcd3764151fb1..534d4fed39a36 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: 2024-06-18 +date: 2024-06-19 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 a3c7ca961734e..4900cf0b98c7c 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: 2024-06-18 +date: 2024-06-19 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 e952e747c1c0d..1b19fa053acc1 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: 2024-06-18 +date: 2024-06-19 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 f02fa1ee652b9..feb5fad5b9042 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: 2024-06-18 +date: 2024-06-19 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 1ea8516125ece..47d8c928be47e 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_esql_ast.devdocs.json b/api_docs/kbn_esql_ast.devdocs.json index 870bb8da9db78..8449e60698bff 100644 --- a/api_docs/kbn_esql_ast.devdocs.json +++ b/api_docs/kbn_esql_ast.devdocs.json @@ -1302,7 +1302,19 @@ "docId": "kibKbnEsqlAstPluginApi", "section": "def-common.ESQLCommandMode", "text": "ESQLCommandMode" - } + }, + " | ", + "ESQLInlineCast", + "<", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLAstItem", + "text": "ESQLAstItem" + }, + "> | ", + "ESQLUnknownItem" ], "path": "packages/kbn-esql-ast/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_esql_ast.mdx b/api_docs/kbn_esql_ast.mdx index df1043fcfa395..2a28cd4a0e37a 100644 --- a/api_docs/kbn_esql_ast.mdx +++ b/api_docs/kbn_esql_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-ast title: "@kbn/esql-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-ast plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 68 | 1 | 68 | 7 | +| 68 | 1 | 68 | 9 | ## Common diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 821d90db7c9a3..05bc1416a8a73 100644 --- a/api_docs/kbn_esql_utils.mdx +++ b/api_docs/kbn_esql_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-utils title: "@kbn/esql-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-utils'] --- import kbnEsqlUtilsObj from './kbn_esql_utils.devdocs.json'; diff --git a/api_docs/kbn_esql_validation_autocomplete.devdocs.json b/api_docs/kbn_esql_validation_autocomplete.devdocs.json index 75d1a0843c498..ea46ea3ba35da 100644 --- a/api_docs/kbn_esql_validation_autocomplete.devdocs.json +++ b/api_docs/kbn_esql_validation_autocomplete.devdocs.json @@ -19,6 +19,106 @@ "common": { "classes": [], "functions": [ + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.checkFunctionArgMatchesDefinition", + "type": "Function", + "tags": [], + "label": "checkFunctionArgMatchesDefinition", + "description": [ + "\nChecks if an AST function argument is of the correct type\ngiven the definition." + ], + "signature": [ + "(arg: ", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLSingleAstItem", + "text": "ESQLSingleAstItem" + }, + ", parameterDefinition: { name: string; type: ", + "FunctionParameterType", + "; optional?: boolean | undefined; noNestingFunctions?: boolean | undefined; supportsWildcard?: boolean | undefined; constantOnly?: boolean | undefined; literalOptions?: string[] | undefined; literalSuggestions?: string[] | undefined; }, references: ", + "ReferenceMaps", + ", parentCommand: string | undefined) => boolean | undefined" + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.checkFunctionArgMatchesDefinition.$1", + "type": "CompoundType", + "tags": [], + "label": "arg", + "description": [], + "signature": [ + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLSingleAstItem", + "text": "ESQLSingleAstItem" + } + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.checkFunctionArgMatchesDefinition.$2", + "type": "Object", + "tags": [], + "label": "parameterDefinition", + "description": [], + "signature": [ + "{ name: string; type: ", + "FunctionParameterType", + "; optional?: boolean | undefined; noNestingFunctions?: boolean | undefined; supportsWildcard?: boolean | undefined; constantOnly?: boolean | undefined; literalOptions?: string[] | undefined; literalSuggestions?: string[] | undefined; }" + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.checkFunctionArgMatchesDefinition.$3", + "type": "Object", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "ReferenceMaps" + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.checkFunctionArgMatchesDefinition.$4", + "type": "string", + "tags": [], + "label": "parentCommand", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/esql-validation-autocomplete", "id": "def-common.collectVariables", @@ -121,72 +221,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.columnExists", - "type": "Function", - "tags": [], - "label": "columnExists", - "description": [], - "signature": [ - "(column: ", - { - "pluginId": "@kbn/esql-ast", - "scope": "common", - "docId": "kibKbnEsqlAstPluginApi", - "section": "def-common.ESQLColumn", - "text": "ESQLColumn" - }, - ", { fields, variables }: Pick<", - "ReferenceMaps", - ", \"fields\" | \"variables\">) => { hit: boolean; nameHit: string; } | { hit: boolean; nameHit?: undefined; }" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.columnExists.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "@kbn/esql-ast", - "scope": "common", - "docId": "kibKbnEsqlAstPluginApi", - "section": "def-common.ESQLColumn", - "text": "ESQLColumn" - } - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.columnExists.$2", - "type": "Object", - "tags": [], - "label": "{ fields, variables }", - "description": [], - "signature": [ - "Pick<", - "ReferenceMaps", - ", \"fields\" | \"variables\">" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/esql-validation-autocomplete", "id": "def-common.getActions", @@ -601,6 +635,18 @@ "section": "def-common.ESQLCommandMode", "text": "ESQLCommandMode" }, + " | ", + "ESQLInlineCast", + "<", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLAstItem", + "text": "ESQLAstItem" + }, + "> | ", + "ESQLUnknownItem", "; option: ", { "pluginId": "@kbn/esql-ast", @@ -699,6 +745,18 @@ "section": "def-common.ESQLCommandMode", "text": "ESQLCommandMode" }, + " | ", + "ESQLInlineCast", + "<", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLAstItem", + "text": "ESQLAstItem" + }, + "> | ", + "ESQLUnknownItem", " | undefined; option: ", { "pluginId": "@kbn/esql-ast", @@ -781,6 +839,18 @@ "section": "def-common.ESQLCommandMode", "text": "ESQLCommandMode" }, + " | ", + "ESQLInlineCast", + "<", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLAstItem", + "text": "ESQLAstItem" + }, + "> | ", + "ESQLUnknownItem", " | undefined; option: ", { "pluginId": "@kbn/esql-ast", @@ -871,6 +941,18 @@ "section": "def-common.ESQLCommandMode", "text": "ESQLCommandMode" }, + " | ", + "ESQLInlineCast", + "<", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLAstItem", + "text": "ESQLAstItem" + }, + "> | ", + "ESQLUnknownItem", " | undefined; setting: ", { "pluginId": "@kbn/esql-ast", @@ -940,89 +1022,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.getColumnHit", - "type": "Function", - "tags": [], - "label": "getColumnHit", - "description": [], - "signature": [ - "(columnName: string, { fields, variables }: Pick<", - "ReferenceMaps", - ", \"fields\" | \"variables\">, position: number | undefined) => ", - { - "pluginId": "@kbn/esql-validation-autocomplete", - "scope": "common", - "docId": "kibKbnEsqlValidationAutocompletePluginApi", - "section": "def-common.ESQLVariable", - "text": "ESQLVariable" - }, - " | ", - { - "pluginId": "@kbn/esql-validation-autocomplete", - "scope": "common", - "docId": "kibKbnEsqlValidationAutocompletePluginApi", - "section": "def-common.ESQLRealField", - "text": "ESQLRealField" - }, - " | undefined" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.getColumnHit.$1", - "type": "string", - "tags": [], - "label": "columnName", - "description": [], - "signature": [ - "string" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.getColumnHit.$2", - "type": "Object", - "tags": [], - "label": "{ fields, variables }", - "description": [], - "signature": [ - "Pick<", - "ReferenceMaps", - ", \"fields\" | \"variables\">" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.getColumnHit.$3", - "type": "number", - "tags": [], - "label": "position", - "description": [], - "signature": [ - "number | undefined" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/esql-validation-autocomplete", "id": "def-common.getCommandDefinition", @@ -1353,7 +1352,7 @@ "section": "def-common.ESQLCallbacks", "text": "ESQLCallbacks" }, - " | undefined) => () => Promise<{ name: string; hidden: boolean; }[]>" + " | undefined) => () => Promise<{ name: string; hidden: boolean; title?: string | undefined; dataStreams?: { name: string; title?: string | undefined; }[] | undefined; }[]>" ], "path": "packages/kbn-esql-validation-autocomplete/src/shared/resources_helpers.ts", "deprecated": false, @@ -1527,121 +1526,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.isEqualType", - "type": "Function", - "tags": [], - "label": "isEqualType", - "description": [ - "\nChecks if an AST argument is of the correct type\ngiven the definition." - ], - "signature": [ - "(arg: ", - { - "pluginId": "@kbn/esql-ast", - "scope": "common", - "docId": "kibKbnEsqlAstPluginApi", - "section": "def-common.ESQLSingleAstItem", - "text": "ESQLSingleAstItem" - }, - ", argDef: { name: string; type: ", - "FunctionParameterType", - "; optional?: boolean | undefined; noNestingFunctions?: boolean | undefined; supportsWildcard?: boolean | undefined; constantOnly?: boolean | undefined; literalOptions?: string[] | undefined; literalSuggestions?: string[] | undefined; } | { name: string; type: string; optional?: boolean | undefined; innerType?: string | undefined; values?: string[] | undefined; valueDescriptions?: string[] | undefined; constantOnly?: boolean | undefined; wildcards?: boolean | undefined; }, references: ", - "ReferenceMaps", - ", parentCommand: string | undefined, nameHit: string | undefined) => boolean | undefined" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.isEqualType.$1", - "type": "CompoundType", - "tags": [], - "label": "arg", - "description": [], - "signature": [ - { - "pluginId": "@kbn/esql-ast", - "scope": "common", - "docId": "kibKbnEsqlAstPluginApi", - "section": "def-common.ESQLSingleAstItem", - "text": "ESQLSingleAstItem" - } - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.isEqualType.$2", - "type": "CompoundType", - "tags": [], - "label": "argDef", - "description": [], - "signature": [ - "{ name: string; type: ", - "FunctionParameterType", - "; optional?: boolean | undefined; noNestingFunctions?: boolean | undefined; supportsWildcard?: boolean | undefined; constantOnly?: boolean | undefined; literalOptions?: string[] | undefined; literalSuggestions?: string[] | undefined; } | { name: string; type: string; optional?: boolean | undefined; innerType?: string | undefined; values?: string[] | undefined; valueDescriptions?: string[] | undefined; constantOnly?: boolean | undefined; wildcards?: boolean | undefined; }" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.isEqualType.$3", - "type": "Object", - "tags": [], - "label": "references", - "description": [], - "signature": [ - "ReferenceMaps" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.isEqualType.$4", - "type": "string", - "tags": [], - "label": "parentCommand", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - }, - { - "parentPluginId": "@kbn/esql-validation-autocomplete", - "id": "def-common.isEqualType.$5", - "type": "string", - "tags": [], - "label": "nameHit", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/esql-validation-autocomplete", "id": "def-common.isExpression", @@ -2083,6 +1967,90 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.lookupColumn", + "type": "Function", + "tags": [], + "label": "lookupColumn", + "description": [ + "\nThis function returns the variable or field matching a column" + ], + "signature": [ + "(column: ", + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLColumn", + "text": "ESQLColumn" + }, + ", { fields, variables }: Pick<", + "ReferenceMaps", + ", \"fields\" | \"variables\">) => ", + { + "pluginId": "@kbn/esql-validation-autocomplete", + "scope": "common", + "docId": "kibKbnEsqlValidationAutocompletePluginApi", + "section": "def-common.ESQLVariable", + "text": "ESQLVariable" + }, + " | ", + { + "pluginId": "@kbn/esql-validation-autocomplete", + "scope": "common", + "docId": "kibKbnEsqlValidationAutocompletePluginApi", + "section": "def-common.ESQLRealField", + "text": "ESQLRealField" + }, + " | undefined" + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.lookupColumn.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "@kbn/esql-ast", + "scope": "common", + "docId": "kibKbnEsqlAstPluginApi", + "section": "def-common.ESQLColumn", + "text": "ESQLColumn" + } + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/esql-validation-autocomplete", + "id": "def-common.lookupColumn.$2", + "type": "Object", + "tags": [], + "label": "{ fields, variables }", + "description": [], + "signature": [ + "Pick<", + "ReferenceMaps", + ", \"fields\" | \"variables\">" + ], + "path": "packages/kbn-esql-validation-autocomplete/src/shared/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/esql-validation-autocomplete", "id": "def-common.printFunctionSignature", @@ -2977,7 +2945,7 @@ "label": "getSources", "description": [], "signature": [ - "CallbackFn<{}, { name: string; hidden: boolean; }> | undefined" + "CallbackFn<{}, { name: string; hidden: boolean; title?: string | undefined; dataStreams?: { name: string; title?: string | undefined; }[] | undefined; }> | undefined" ], "path": "packages/kbn-esql-validation-autocomplete/src/shared/types.ts", "deprecated": false, diff --git a/api_docs/kbn_esql_validation_autocomplete.mdx b/api_docs/kbn_esql_validation_autocomplete.mdx index 8cf5a9051dac7..f326d93d5c638 100644 --- a/api_docs/kbn_esql_validation_autocomplete.mdx +++ b/api_docs/kbn_esql_validation_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-validation-autocomplete title: "@kbn/esql-validation-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-validation-autocomplete plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-validation-autocomplete'] --- import kbnEsqlValidationAutocompleteObj from './kbn_esql_validation_autocomplete.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 194 | 0 | 184 | 10 | +| 189 | 0 | 178 | 10 | ## Common diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 195dcc7f252e4..93754c21b806c 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index cd2ffd5dc03be..7b083d3bdcdcb 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index ddf980c788095..97773962b0371 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 0dbb4516f899b..a0cab91e0732e 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index 607e6e85b5b86..61c5a7cc45dbe 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 5c30aa5758223..516e28902c830 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: 2024-06-18 +date: 2024-06-19 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_formatters.mdx b/api_docs/kbn_formatters.mdx index 6badbde276ef9..55ad163620e2a 100644 --- a/api_docs/kbn_formatters.mdx +++ b/api_docs/kbn_formatters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-formatters title: "@kbn/formatters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/formatters plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/formatters'] --- import kbnFormattersObj from './kbn_formatters.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 7d14b862832b8..76a7e2562c5f3 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: 2024-06-18 +date: 2024-06-19 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_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index 0816a776cc2d8..eb5e6081a592f 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 273f2e8ae9706..377d3f28132a8 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index 6e04d34d1e580..aeb4254520b6a 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 89d00a9f4726b..0dfb7c3ed231d 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index c58584592fe2d..abe0caab761c9 100644 --- a/api_docs/kbn_grouping.mdx +++ b/api_docs/kbn_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grouping title: "@kbn/grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grouping plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grouping'] --- import kbnGroupingObj from './kbn_grouping.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index f0c50d75baef5..d77bf48458c7c 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: 2024-06-18 +date: 2024-06-19 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 92086810350ea..2b379b261a2a2 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: 2024-06-18 +date: 2024-06-19 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 dc2e61157905c..6246e2e784241 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: 2024-06-18 +date: 2024-06-19 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 8b15c7a251945..bd4698775dfcd 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: 2024-06-18 +date: 2024-06-19 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 2411e3232b526..3bdc220beb3a5 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: 2024-06-18 +date: 2024-06-19 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 df62efebdf048..0fac54d1c4056 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: 2024-06-18 +date: 2024-06-19 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 00596b5b41162..1be4bfe0b0f67 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: 2024-06-18 +date: 2024-06-19 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 5b9256cbf9013..aac51775cf05d 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: 2024-06-18 +date: 2024-06-19 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 994dc23e2cdee..758d716f10029 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_management.mdx b/api_docs/kbn_index_management.mdx index 4216389c07d07..c2daabbf703aa 100644 --- a/api_docs/kbn_index_management.mdx +++ b/api_docs/kbn_index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management title: "@kbn/index-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management'] --- import kbnIndexManagementObj from './kbn_index_management.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index 2fd7b7701b5a5..95cae23bb1c3f 100644 --- a/api_docs/kbn_inference_integration_flyout.mdx +++ b/api_docs/kbn_inference_integration_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference_integration_flyout title: "@kbn/inference_integration_flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference_integration_flyout plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference_integration_flyout'] --- import kbnInferenceIntegrationFlyoutObj from './kbn_inference_integration_flyout.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index a70f1d03f26a1..91815af1a7baf 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index e17dbf002a965..5bd2f82a476b5 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: 2024-06-18 +date: 2024-06-19 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 09c2f90cf9a64..7806977a5ff63 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_ipynb.mdx b/api_docs/kbn_ipynb.mdx index 613484e3bcc1b..0f55e6da22faa 100644 --- a/api_docs/kbn_ipynb.mdx +++ b/api_docs/kbn_ipynb.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ipynb title: "@kbn/ipynb" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ipynb plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index c199e942c4736..e2e126ace151e 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: 2024-06-18 +date: 2024-06-19 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 2168b89479953..f92880e152af6 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: 2024-06-18 +date: 2024-06-19 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 7b38a3b47dbbe..f7a970eade436 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: 2024-06-18 +date: 2024-06-19 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 e069b954427bd..719fe13148e43 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: 2024-06-18 +date: 2024-06-19 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 a694f2381cdb4..edcf7b993d47c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index 654988afdd9ad..b8b7b8305838e 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index 389fc614a9d04..dcc7887e2c389 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index ac5cc472bd957..0b3284ccaff5b 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: 2024-06-18 +date: 2024-06-19 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 a7c06f39b8891..e7296264e4221 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_content_badge.mdx b/api_docs/kbn_managed_content_badge.mdx index c1e7cc6cb2950..ade696d52c11e 100644 --- a/api_docs/kbn_managed_content_badge.mdx +++ b/api_docs/kbn_managed_content_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-content-badge title: "@kbn/managed-content-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-content-badge plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-content-badge'] --- import kbnManagedContentBadgeObj from './kbn_managed_content_badge.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index c4805f5d06330..9ea1627776fdd 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index fa34a83354fba..e57cd5e7ed8fa 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index a35cbf8d26019..bfe63ca555d66 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index be9c1a2e0b319..679ecc142d451 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 35b8de7da8653..5466ac9f12882 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index e32b94df5ef88..389e2027f424a 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index ecade74c4d985..ad499b3c90f10 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index 03952391dbad1..2886e76ab1137 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 9a3bbd297ed9b..d4d30d03b2e60 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 8ecac5821b8d7..d386b31cc29bb 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index 7f77615f09a8f..960d7c89e444c 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 02190e2aac699..f846a138ad72d 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index dac4c65101db2..cc94cfcc45577 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.devdocs.json b/api_docs/kbn_mapbox_gl.devdocs.json index 89aaae69b68dd..7f8b965b1d5c2 100644 --- a/api_docs/kbn_mapbox_gl.devdocs.json +++ b/api_docs/kbn_mapbox_gl.devdocs.json @@ -9592,7 +9592,7 @@ "label": "MapEvent", "description": [], "signature": [ - "\"error\" | \"data\" | \"render\" | \"remove\" | \"rotate\" | \"resize\" | \"idle\" | \"zoom\" | \"load\" | \"move\" | \"mousedown\" | \"mouseup\" | \"mouseover\" | \"mousemove\" | \"click\" | \"dblclick\" | \"mouseenter\" | \"mouseleave\" | \"mouseout\" | \"contextmenu\" | \"wheel\" | \"touchstart\" | \"touchend\" | \"touchmove\" | \"touchcancel\" | \"movestart\" | \"moveend\" | \"dragstart\" | \"drag\" | \"dragend\" | \"zoomstart\" | \"zoomend\" | \"rotatestart\" | \"rotateend\" | \"pitchstart\" | \"pitch\" | \"pitchend\" | \"boxzoomstart\" | \"boxzoomend\" | \"boxzoomcancel\" | \"webglcontextlost\" | \"webglcontextrestored\" | \"styledata\" | \"sourcedata\" | \"dataloading\" | \"styledataloading\" | \"sourcedataloading\" | \"styleimagemissing\" | \"style.load\" | \"terrain\" | \"dataabort\" | \"sourcedataabort\"" + "\"error\" | \"data\" | \"move\" | \"render\" | \"remove\" | \"rotate\" | \"resize\" | \"idle\" | \"zoom\" | \"load\" | \"mousedown\" | \"mouseup\" | \"mouseover\" | \"mousemove\" | \"click\" | \"dblclick\" | \"mouseenter\" | \"mouseleave\" | \"mouseout\" | \"contextmenu\" | \"wheel\" | \"touchstart\" | \"touchend\" | \"touchmove\" | \"touchcancel\" | \"movestart\" | \"moveend\" | \"dragstart\" | \"drag\" | \"dragend\" | \"zoomstart\" | \"zoomend\" | \"rotatestart\" | \"rotateend\" | \"pitchstart\" | \"pitch\" | \"pitchend\" | \"boxzoomstart\" | \"boxzoomend\" | \"boxzoomcancel\" | \"webglcontextlost\" | \"webglcontextrestored\" | \"styledata\" | \"sourcedata\" | \"dataloading\" | \"styledataloading\" | \"sourcedataloading\" | \"styleimagemissing\" | \"style.load\" | \"terrain\" | \"dataabort\" | \"sourcedataabort\"" ], "path": "node_modules/maplibre-gl/dist/maplibre-gl.d.ts", "deprecated": false, diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 5d95f72358409..29fe8a26cc807 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index be9bcb20e4aca..6b6ab7809564d 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 3a2e1d8eb4855..c682754234786 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: 2024-06-18 +date: 2024-06-19 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_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index 3b4dc8c8dbe19..f94006b655dbf 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_cancellable_search.mdx b/api_docs/kbn_ml_cancellable_search.mdx index 7fda32a6202b6..bd45f8ad1a08b 100644 --- a/api_docs/kbn_ml_cancellable_search.mdx +++ b/api_docs/kbn_ml_cancellable_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-cancellable-search title: "@kbn/ml-cancellable-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-cancellable-search plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-cancellable-search'] --- import kbnMlCancellableSearchObj from './kbn_ml_cancellable_search.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index bddad4be53cfe..5f6b80c05feb8 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index 44c318ad0633a..5869e96f4d4a2 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index 899f0313c8a10..dfdc3b08cbacf 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index e664eaa61d424..8a1cd3f0ad4e7 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index cebdf85867838..c0466967360b1 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: 2024-06-18 +date: 2024-06-19 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_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index f75310c36f61f..da283ea5b2848 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index 510e1542d0f11..52e09fb58f798 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index ec6dec9b9d60c..7f261994b433c 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index bd53464f3382e..f60bb413a2382 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: 2024-06-18 +date: 2024-06-19 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 3739aefe3f9d3..80a615093e7f0 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: 2024-06-18 +date: 2024-06-19 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_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index 040eecbaf5325..d6cb7980ec60d 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 63e5c5d6286ec..f5bce0abc160d 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: 2024-06-18 +date: 2024-06-19 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 3bb1ec9642670..2925c0b6db445 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: 2024-06-18 +date: 2024-06-19 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_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index 815921c27fdfd..4bfee361313a4 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 8c6dc446dafbd..4b5f183519c84 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: 2024-06-18 +date: 2024-06-19 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_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index 7733cd5ed1572..f5fb6b5a066d8 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index 008b2619d5bd9..a85bf8421e6c0 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index 9d976957fa693..ee9cc56bc047a 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 1b45e8ff581a6..7100105fa361a 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: 2024-06-18 +date: 2024-06-19 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_time_buckets.mdx b/api_docs/kbn_ml_time_buckets.mdx index 9bed3e7d98e82..7a1829d634b78 100644 --- a/api_docs/kbn_ml_time_buckets.mdx +++ b/api_docs/kbn_ml_time_buckets.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-time-buckets title: "@kbn/ml-time-buckets" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-time-buckets plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-time-buckets'] --- import kbnMlTimeBucketsObj from './kbn_ml_time_buckets.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 9f171d79b9144..34e51866932da 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 11c518e24b374..88be9a7227836 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index d2cda31264ab9..68f724104cb2c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index 4a35bdacaf30c..d56e817f32cfe 100644 --- a/api_docs/kbn_mock_idp_utils.mdx +++ b/api_docs/kbn_mock_idp_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mock-idp-utils title: "@kbn/mock-idp-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mock-idp-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mock-idp-utils'] --- import kbnMockIdpUtilsObj from './kbn_mock_idp_utils.devdocs.json'; diff --git a/api_docs/kbn_monaco.devdocs.json b/api_docs/kbn_monaco.devdocs.json index e8cc403b3ee30..a432c6389bae2 100644 --- a/api_docs/kbn_monaco.devdocs.json +++ b/api_docs/kbn_monaco.devdocs.json @@ -482,7 +482,7 @@ "label": "getSources", "description": [], "signature": [ - "CallbackFn<{}, { name: string; hidden: boolean; }> | undefined" + "CallbackFn<{}, { name: string; hidden: boolean; title?: string | undefined; dataStreams?: { name: string; title?: string | undefined; }[] | undefined; }> | undefined" ], "path": "packages/kbn-esql-validation-autocomplete/src/shared/types.ts", "deprecated": false, diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 3c3e4138c779f..23ac7c7f51194 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 9992ebe20caaa..bce22ad4b56e8 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index 1dc5321bcf697..ab2abedacdfb7 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index f6153a9f6c1f9..6f86bf5ff4e02 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 7f3e670bbeea4..2cefb2e5feaa8 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 88d28ea4a83c0..6f7bcb21157f8 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 418286506e3b3..a3843270d5540 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index c3473550ecdfe..32c15b1d0581a 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: 2024-06-18 +date: 2024-06-19 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 c57daa10853f1..0d8c3816185a8 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: 2024-06-18 +date: 2024-06-19 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 6e1598dfce37b..d27bd79efae83 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: 2024-06-18 +date: 2024-06-19 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_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 509330b3de5dc..998c16ed1affb 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 3033ba99f1bf1..4c5416e26ed0f 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: 2024-06-18 +date: 2024-06-19 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_check.mdx b/api_docs/kbn_plugin_check.mdx index ea93f44e2c8cf..b27b01dcff788 100644 --- a/api_docs/kbn_plugin_check.mdx +++ b/api_docs/kbn_plugin_check.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-check title: "@kbn/plugin-check" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-check plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-check'] --- import kbnPluginCheckObj from './kbn_plugin_check.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 52b89d3991c20..586db8494bb0c 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: 2024-06-18 +date: 2024-06-19 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 ccfb2e0a5ffe9..6ef469883b64e 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_presentation_containers.mdx b/api_docs/kbn_presentation_containers.mdx index c5fbf9f7dd1a5..86b3132502f3c 100644 --- a/api_docs/kbn_presentation_containers.mdx +++ b/api_docs/kbn_presentation_containers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-containers title: "@kbn/presentation-containers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-containers plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-containers'] --- import kbnPresentationContainersObj from './kbn_presentation_containers.devdocs.json'; diff --git a/api_docs/kbn_presentation_publishing.mdx b/api_docs/kbn_presentation_publishing.mdx index 57d89d5280500..0e021d0ca307c 100644 --- a/api_docs/kbn_presentation_publishing.mdx +++ b/api_docs/kbn_presentation_publishing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-publishing title: "@kbn/presentation-publishing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-publishing plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 98d3a52877750..68813cccd6190 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 8422a3507cb45..b29ce64a87355 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 939d4a7780390..f411673525943 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_hooks.mdx b/api_docs/kbn_react_hooks.mdx index b523cd4752ee5..a7443008e4121 100644 --- a/api_docs/kbn_react_hooks.mdx +++ b/api_docs/kbn_react_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-hooks title: "@kbn/react-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-hooks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-hooks'] --- import kbnReactHooksObj from './kbn_react_hooks.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 3d5d27ff2e549..0f8bb09a45811 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index f581c1b14ca09..201f21fd2072d 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index 3b2494976f6aa..23e6f601bf27c 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index 29999416ca2c6..98dcc858cab1f 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index c52481c92a2fa..5f617bee8c48c 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index a0347314f8751..fb82a4b897546 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 77e725cfae3fa..7f7f696d78a68 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: 2024-06-18 +date: 2024-06-19 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 aa0bd6217293f..fb5c4a1524b4d 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: 2024-06-18 +date: 2024-06-19 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 d6a38392579e9..5a840e912f536 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: 2024-06-18 +date: 2024-06-19 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 f017da06d9281..3ff67fc3ea8ce 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 14bafe45835dc..89ec0443f6839 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_csv_share_panel.mdx b/api_docs/kbn_reporting_csv_share_panel.mdx index 037f4030f520a..ce737fb4e4b06 100644 --- a/api_docs/kbn_reporting_csv_share_panel.mdx +++ b/api_docs/kbn_reporting_csv_share_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-csv-share-panel title: "@kbn/reporting-csv-share-panel" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-csv-share-panel plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-csv-share-panel'] --- import kbnReportingCsvSharePanelObj from './kbn_reporting_csv_share_panel.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index 4e6da9fa82d13..00ce6fed4ce0b 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index 954b82beae3f0..03cc56bb5dd51 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index 946ebba102d94..2737f4db07ce4 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index bd28fcbcd60ff..574ac8e9ca734 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index 5a3d3485a84a3..2977c93c5c0c4 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index 21a561c316f91..1fe929de376f3 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index 502c9b53594fc..80424616f17b4 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index af99797625498..2bdca194559a5 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index 0ed4f1d634e57..b1e93c3e64713 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 8f3ff9bd87637..2cd1f2d49eaff 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_feature_flag_service.mdx b/api_docs/kbn_response_ops_feature_flag_service.mdx index 538573427a564..832f03fdfeb36 100644 --- a/api_docs/kbn_response_ops_feature_flag_service.mdx +++ b/api_docs/kbn_response_ops_feature_flag_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-feature-flag-service title: "@kbn/response-ops-feature-flag-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-feature-flag-service plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-feature-flag-service'] --- import kbnResponseOpsFeatureFlagServiceObj from './kbn_response_ops_feature_flag_service.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index abf549f7879de..02fe8a3f84e65 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index 189a616816212..3a36a6cad5926 100644 --- a/api_docs/kbn_router_to_openapispec.mdx +++ b/api_docs/kbn_router_to_openapispec.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-to-openapispec title: "@kbn/router-to-openapispec" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-to-openapispec plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-to-openapispec'] --- import kbnRouterToOpenapispecObj from './kbn_router_to_openapispec.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index d2bc968cce112..ff48953d6b839 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index 6753bb86d6d85..2938c97001f60 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 7f70d045f06ee..bcc4f8825b62b 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index b68bf847f8b02..3f3dd6ae50a6d 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 241233903437a..180f6feaa00b6 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.devdocs.json b/api_docs/kbn_search_connectors.devdocs.json index 2a82021bac368..3cf388d6f1656 100644 --- a/api_docs/kbn_search_connectors.devdocs.json +++ b/api_docs/kbn_search_connectors.devdocs.json @@ -6499,23 +6499,23 @@ "section": "def-common.ConnectorStatus", "text": "ConnectorStatus" }, - "; description: string | null; language: string | null; configuration: ", + "; description: string | null; language: string | null; pipeline?: ", { "pluginId": "@kbn/search-connectors", "scope": "common", "docId": "kibKbnSearchConnectorsPluginApi", - "section": "def-common.ConnectorConfiguration", - "text": "ConnectorConfiguration" + "section": "def-common.IngestPipelineParams", + "text": "IngestPipelineParams" }, - "; index_name: string | null; pipeline?: ", + " | null | undefined; configuration: ", { "pluginId": "@kbn/search-connectors", "scope": "common", "docId": "kibKbnSearchConnectorsPluginApi", - "section": "def-common.IngestPipelineParams", - "text": "IngestPipelineParams" + "section": "def-common.ConnectorConfiguration", + "text": "ConnectorConfiguration" }, - " | null | undefined; api_key_id: string | null; api_key_secret_id: string | null; custom_scheduling: ", + "; index_name: string | null; api_key_id: string | null; api_key_secret_id: string | null; custom_scheduling: ", { "pluginId": "@kbn/search-connectors", "scope": "common", diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 61f576ccec4c4..b9c9c36ee0cc4 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index c04430411fd4e..95d9c212126d9 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index ee933ffadffc5..af6487fc4bd74 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index a4911af523c9f..164bc07bfde00 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index dacc0a63e4c55..bde8f9b48769a 100644 --- a/api_docs/kbn_search_types.mdx +++ b/api_docs/kbn_search_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-types title: "@kbn/search-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index c1d99a522e9bc..d77972c92b169 100644 --- a/api_docs/kbn_security_hardening.mdx +++ b/api_docs/kbn_security_hardening.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-hardening title: "@kbn/security-hardening" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-hardening plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-hardening'] --- import kbnSecurityHardeningObj from './kbn_security_hardening.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index 78ab45087fb48..6af26b6b71fbf 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 64ee1ad1bd645..e9c43ae092a19 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index 7476a1f55a9f4..1e2222e5ee35b 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 1ec8908ff8655..9d91ab7470056 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index f3762cab5063e..6bf6254bc2591 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index 63f4a70fb155c..d011760047994 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index 1d7460b5e9c07..168d289b799cd 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 337f9ac61e761..2ac141175ccf8 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 7737f3b2578f9..d6a3696437744 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 0e9c907dcd407..8762cacb033b3 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: 2024-06-18 +date: 2024-06-19 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 787dc2539f43f..ff2f0609cc740 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: 2024-06-18 +date: 2024-06-19 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 8693ad038c7fd..09104e8d6febc 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: 2024-06-18 +date: 2024-06-19 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 da917f28d8f8f..873699f6b4092 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: 2024-06-18 +date: 2024-06-19 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 a72ea475312b4..68eaaad8c99b1 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: 2024-06-18 +date: 2024-06-19 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 07d7b4f7cc05b..c78391812aced 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: 2024-06-18 +date: 2024-06-19 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 843e91cd41738..fdabec7085bb6 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: 2024-06-18 +date: 2024-06-19 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 af215ed77ffa2..dd230ff4e75d2 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: 2024-06-18 +date: 2024-06-19 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 57d831ae429c5..69cb2d0521c29 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: 2024-06-18 +date: 2024-06-19 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 63316808fdde3..6b3e626eccecf 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: 2024-06-18 +date: 2024-06-19 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 28a0375931771..a2a939321dd14 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: 2024-06-18 +date: 2024-06-19 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 d5b841b270615..11a08c128e4f5 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: 2024-06-18 +date: 2024-06-19 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 f444befb87ea9..ef5bf78923fbd 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: 2024-06-18 +date: 2024-06-19 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 825c6d54bda3c..21bee7c0e72a2 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: 2024-06-18 +date: 2024-06-19 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 59e218ff76cb3..dc2b54cb365bd 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: 2024-06-18 +date: 2024-06-19 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 aa80f0b9ec573..1f2f176f841e3 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: 2024-06-18 +date: 2024-06-19 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 811665eb47b51..7bf9a997101b8 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index c60933aa55a3b..ca8a403348209 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index 79fd5ca3170ce..16ca494177e31 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 3786cf44243be..e52d006de0233 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index f98f68069a3d1..d5b634131da1a 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 9fa1a0a96fc5e..3caf5ac24cec2 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 86bb254e27cee..08bc40afae32c 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index d055e16990504..9745ecdb8186c 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: 2024-06-18 +date: 2024-06-19 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 f9430a3121623..404f874299660 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: 2024-06-18 +date: 2024-06-19 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_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 479d22cd7919b..9333d04496cb4 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: 2024-06-18 +date: 2024-06-19 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_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index f2f59187e78bd..ef29350965f53 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index f7bcd8a674ca2..d3673b25f72e7 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: 2024-06-18 +date: 2024-06-19 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 c8f79c0b8358e..5cb78c021e1f9 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: 2024-06-18 +date: 2024-06-19 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_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index a3f3cb94eb74e..0a2ead2d37889 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index 6927e6aef13c5..239d1b323afe6 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index b638794940fb2..b8ece7498308d 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: 2024-06-18 +date: 2024-06-19 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 fe51f1707507a..d66a1c29d299b 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: 2024-06-18 +date: 2024-06-19 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 282088305558b..4af0208d8e674 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: 2024-06-18 +date: 2024-06-19 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 16d456a7c75b4..da0e05f1c19c1 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: 2024-06-18 +date: 2024-06-19 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 b431671ab16b3..2f8bbde5a2807 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: 2024-06-18 +date: 2024-06-19 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_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 6c1c20a32139f..3bd1daa4136c0 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 5b8d449359e9b..259a2ef67160a 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: 2024-06-18 +date: 2024-06-19 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 f45045dcaffab..fbd2ad9877dfa 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: 2024-06-18 +date: 2024-06-19 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 1f2e3ff7d743a..b43f928c2921b 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: 2024-06-18 +date: 2024-06-19 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 ce75751d7cb98..29a5b2b890b55 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: 2024-06-18 +date: 2024-06-19 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 c35451215f230..70cd3f8c5a62e 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: 2024-06-18 +date: 2024-06-19 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.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index cf0a2a23e81ec..e92d85b21dea6 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: 2024-06-18 +date: 2024-06-19 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 7d7ecdc6922e8..279b0490c5cba 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: 2024-06-18 +date: 2024-06-19 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 f772e6004e16d..17edc6261ff59 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: 2024-06-18 +date: 2024-06-19 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 5be2c91a22b83..073fc1ac1af79 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: 2024-06-18 +date: 2024-06-19 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 887a31b40b280..17fcd1e4f0c90 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: 2024-06-18 +date: 2024-06-19 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 7511487ba56bf..fe6a0f30a222d 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: 2024-06-18 +date: 2024-06-19 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 88c3b4d5eb75f..1657db0e5712d 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: 2024-06-18 +date: 2024-06-19 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 0ce60fec248f9..faa0052cdefe5 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: 2024-06-18 +date: 2024-06-19 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 831e5bdba8652..095b8d4616d75 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: 2024-06-18 +date: 2024-06-19 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 7740c3e4c160c..bff0a5c9cfbcd 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: 2024-06-18 +date: 2024-06-19 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 13423d36e33c6..bf07f8e2bbba6 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: 2024-06-18 +date: 2024-06-19 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 be82ba5e352dd..adf63c4ec483b 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: 2024-06-18 +date: 2024-06-19 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 a7bb6856b2dc5..5287ba423855e 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: 2024-06-18 +date: 2024-06-19 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 6fc5f819983cf..33ab370ae2fac 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: 2024-06-18 +date: 2024-06-19 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 e53ad09f41e05..4029b95750832 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: 2024-06-18 +date: 2024-06-19 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 6144fc2b154d3..92f3ebba2f5df 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: 2024-06-18 +date: 2024-06-19 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 638e6c72f0cea..12cbb0872b2e1 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: 2024-06-18 +date: 2024-06-19 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 69068b73c4fb5..d39b8ab858fc2 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: 2024-06-18 +date: 2024-06-19 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 d2ece90392a85..b82e7bc78626a 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: 2024-06-18 +date: 2024-06-19 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_tabbed_modal.mdx b/api_docs/kbn_shared_ux_tabbed_modal.mdx index 7d52676fbebc4..261247fd4298c 100644 --- a/api_docs/kbn_shared_ux_tabbed_modal.mdx +++ b/api_docs/kbn_shared_ux_tabbed_modal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-tabbed-modal title: "@kbn/shared-ux-tabbed-modal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-tabbed-modal plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-tabbed-modal'] --- import kbnSharedUxTabbedModalObj from './kbn_shared_ux_tabbed_modal.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 23ce9cf96a2a8..1a435031fb47b 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: 2024-06-18 +date: 2024-06-19 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 3a7ba2b4f2f63..aa10690cafe76 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: 2024-06-18 +date: 2024-06-19 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 14d5c70653e93..9748374475f97 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_predicates.mdx b/api_docs/kbn_sort_predicates.mdx index 2011280cc0505..8f8c28195b779 100644 --- a/api_docs/kbn_sort_predicates.mdx +++ b/api_docs/kbn_sort_predicates.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-predicates title: "@kbn/sort-predicates" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-predicates plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 3cdbb6cb2c659..c6eab71a6e0c6 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: 2024-06-18 +date: 2024-06-19 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 9252cdc7046f5..0112000b7a26c 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: 2024-06-18 +date: 2024-06-19 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 cd1c35ec26988..943833768aeac 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: 2024-06-18 +date: 2024-06-19 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 d3d2817392972..0d9fa30a0949c 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: 2024-06-18 +date: 2024-06-19 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 4421b40340122..64f82b945cbc0 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_eui_helpers.mdx b/api_docs/kbn_test_eui_helpers.mdx index 1788f6e0829da..29b758c4be49c 100644 --- a/api_docs/kbn_test_eui_helpers.mdx +++ b/api_docs/kbn_test_eui_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-eui-helpers title: "@kbn/test-eui-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-eui-helpers plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-eui-helpers'] --- import kbnTestEuiHelpersObj from './kbn_test_eui_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 16fb734220c89..468d56ee570b1 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: 2024-06-18 +date: 2024-06-19 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 38d549f82a90d..0e0df8e1fee93 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 75e745709a74f..a274863d31ad6 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index 2d097d5e75e74..d3e5ad7feb050 100644 --- a/api_docs/kbn_timerange.mdx +++ b/api_docs/kbn_timerange.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-timerange title: "@kbn/timerange" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/timerange plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/timerange'] --- import kbnTimerangeObj from './kbn_timerange.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 9e716aecc945c..8312393b8890a 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 5bdef7f4e25c6..b8ef08f8eec8f 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_try_in_console.mdx b/api_docs/kbn_try_in_console.mdx index 3c3e9e346edad..94ddd39fdd645 100644 --- a/api_docs/kbn_try_in_console.mdx +++ b/api_docs/kbn_try_in_console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-try-in-console title: "@kbn/try-in-console" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/try-in-console plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/try-in-console'] --- import kbnTryInConsoleObj from './kbn_try_in_console.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index db8ccb63f12c8..b13e774e8dd1d 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: 2024-06-18 +date: 2024-06-19 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 8428e9a42bbd7..83d4f24f65989 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: 2024-06-18 +date: 2024-06-19 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 4acf3eb5e68ba..cf0d74cfcf5d6 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: 2024-06-18 +date: 2024-06-19 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.devdocs.json b/api_docs/kbn_ui_shared_deps_src.devdocs.json index e74492ad28925..5a4f7663f18a0 100644 --- a/api_docs/kbn_ui_shared_deps_src.devdocs.json +++ b/api_docs/kbn_ui_shared_deps_src.devdocs.json @@ -443,17 +443,6 @@ "deprecated": false, "trackAdoption": false }, - { - "parentPluginId": "@kbn/ui-shared-deps-src", - "id": "def-common.externals.elasticeuidisteui_charts_theme", - "type": "string", - "tags": [], - "label": "'@elastic/eui/dist/eui_charts_theme'", - "description": [], - "path": "packages/kbn-ui-shared-deps-src/src/definitions.js", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "@kbn/ui-shared-deps-src", "id": "def-common.externals.hellopangeadnd", diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 45443736b64cf..3e366650b981a 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 56 | 0 | 47 | 0 | +| 55 | 0 | 46 | 0 | ## Common diff --git a/api_docs/kbn_ui_theme.devdocs.json b/api_docs/kbn_ui_theme.devdocs.json index 94f3bf511028b..f7b49a9d755a3 100644 --- a/api_docs/kbn_ui_theme.devdocs.json +++ b/api_docs/kbn_ui_theme.devdocs.json @@ -69,18 +69,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/monaco", - "path": "packages/kbn-monaco/src/esql/lib/esql_theme.ts" - }, - { - "plugin": "@kbn/monaco", - "path": "packages/kbn-monaco/src/esql/lib/esql_theme.ts" - }, - { - "plugin": "@kbn/monaco", - "path": "packages/kbn-monaco/src/esql/lib/esql_theme.ts" - }, { "plugin": "@kbn/monaco", "path": "packages/kbn-monaco/src/esql/lib/esql_theme.ts" diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 11c3a78190214..a316100c89324 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index 6470406f9b3cb..ebaebbf0d1c19 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index 0e904c901ade3..9016bea59786a 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 0b3533175afd7..d7b8892935c74 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index 3529addc44268..13d0692fda595 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_prompt.mdx b/api_docs/kbn_unsaved_changes_prompt.mdx index 6877c9595ecd2..28de503ac92cf 100644 --- a/api_docs/kbn_unsaved_changes_prompt.mdx +++ b/api_docs/kbn_unsaved_changes_prompt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-prompt title: "@kbn/unsaved-changes-prompt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-prompt plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-prompt'] --- import kbnUnsavedChangesPromptObj from './kbn_unsaved_changes_prompt.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 7aa3a96e56451..0e01d98f67532 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 5149cf98e47f9..0eca362028796 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: 2024-06-18 +date: 2024-06-19 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 5fe09a5bb7435..51d6e23f8b802 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: 2024-06-18 +date: 2024-06-19 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 d02ac34ef384f..857110d8f912f 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: 2024-06-18 +date: 2024-06-19 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 3ad836e69f7ad..3de74eb88c3ab 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 7a12739a8a49b..fff13aac1b112 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index 7adc25184d8eb..94cabdfae49a6 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 76384b88894ad..a093809f851a7 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 3912fb378253c..78c6e883b6e67 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.devdocs.json b/api_docs/kbn_zod_helpers.devdocs.json index 2001282ced394..3ea762172aa25 100644 --- a/api_docs/kbn_zod_helpers.devdocs.json +++ b/api_docs/kbn_zod_helpers.devdocs.json @@ -58,6 +58,49 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/zod-helpers", + "id": "def-common.buildRouteValidationWithZod", + "type": "Function", + "tags": [], + "label": "buildRouteValidationWithZod", + "description": [ + "\nZod validation factory for Kibana route's request validation.\nIt allows to pass a Zod schema for parameters, query and/or body validation.\n\nExample:\n\n```ts\nrouter.versioned\n .post({\n access: 'public',\n path: MY_URL,\n })\n .addVersion(\n {\n version: 'my-version',\n validate: {\n request: {\n params: buildRouteValidationWithZod(MyRequestParamsZodSchema),\n query: buildRouteValidationWithZod(MyRequestQueryZodSchema),\n body: buildRouteValidationWithZod(MyRequestBodyZodSchema),\n },\n },\n },\n```" + ], + "signature": [ + "(schema: ZodSchema) => ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.RouteValidationFunction", + "text": "RouteValidationFunction" + }, + "" + ], + "path": "packages/kbn-zod-helpers/src/build_route_validation_with_zod.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/zod-helpers", + "id": "def-common.buildRouteValidationWithZod.$1", + "type": "Uncategorized", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + "ZodSchema" + ], + "path": "packages/kbn-zod-helpers/src/build_route_validation_with_zod.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/zod-helpers", "id": "def-common.expectParseError", diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index 21ca40473b28e..8c5ae93d1de77 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-detection-rule-management](https://github.com/orgs/el | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 18 | 0 | 9 | 0 | +| 20 | 0 | 10 | 0 | ## Common diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 68e7dc0095685..2578cad63ef05 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: 2024-06-18 +date: 2024-06-19 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 a771d0a42ff2f..7eaac80a171b1 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: 2024-06-18 +date: 2024-06-19 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 a7ed980f094eb..350d92ac57c19 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: 2024-06-18 +date: 2024-06-19 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 307f3dc924d14..97af756fbcb2a 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: 2024-06-18 +date: 2024-06-19 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 8d5aa484a4f29..1aacddd53ae9c 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: 2024-06-18 +date: 2024-06-19 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 91f753208affb..52990b67a8805 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: 2024-06-18 +date: 2024-06-19 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 3553269ec96e9..53e6a7de6aaf9 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 05a287f91b129..7ff63218c70ce 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 5dbd8b3e558aa..bb6e28921dcea 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index ab66bbd113633..d1dbb67ba6ccb 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 6f9539d43aac2..8e77013849428 100644 --- a/api_docs/logs_data_access.mdx +++ b/api_docs/logs_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsDataAccess title: "logsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the logsDataAccess plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsDataAccess'] --- import logsDataAccessObj from './logs_data_access.devdocs.json'; diff --git a/api_docs/logs_explorer.mdx b/api_docs/logs_explorer.mdx index 80e08ec4cf6f7..f853c879c5cc2 100644 --- a/api_docs/logs_explorer.mdx +++ b/api_docs/logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsExplorer title: "logsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logsExplorer plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsExplorer'] --- import logsExplorerObj from './logs_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 3f2e723b5579a..b3b4149db03f5 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index ed2c0c3d95e7b..128a57183b207 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: 2024-06-18 +date: 2024-06-19 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 d6f7a1d8cce9a..ada73ac30ea8f 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: 2024-06-18 +date: 2024-06-19 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 11fbb4d97f7e7..dcf3eed8d65e7 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index c1e9164d20921..7621ac99fed0d 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 3d83b78e1cf32..242a6df027850 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index 0d1627d4941c8..a54ec10197db9 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 06c2e7e11e522..f00d547d595b2 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: 2024-06-18 +date: 2024-06-19 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 3f382a0a6f1a3..37bdf4ef856ea 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: 2024-06-18 +date: 2024-06-19 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 4fc030a3e7712..36019f225e1c4 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: 2024-06-18 +date: 2024-06-19 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 056c9b626c0ac..ed3a9bbce6fec 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index 68e23117c862a..2ac60ca6d01aa 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index acdbb39c7900e..fefcc8e26a90f 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 278f66f3723ec..ed3e91babeb4f 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -155,7 +155,7 @@ "label": "AlertSummary", "description": [], "signature": [ - "({ alertSummaryFields }: AlertSummaryProps) => JSX.Element" + "({ alert, alertSummaryFields }: AlertSummaryProps) => JSX.Element" ], "path": "x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx", "deprecated": false, @@ -166,7 +166,7 @@ "id": "def-public.AlertSummary.$1", "type": "Object", "tags": [], - "label": "{ alertSummaryFields }", + "label": "{ alert, alertSummaryFields }", "description": [], "signature": [ "AlertSummaryProps" diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index eb76936ebe69d..8b0145aebed4c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 62922ef331bbf..944c331bf49d7 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index 2d72d3c575926..3d3c4c26a72b5 100644 --- a/api_docs/observability_a_i_assistant_app.mdx +++ b/api_docs/observability_a_i_assistant_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistantApp title: "observabilityAIAssistantApp" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistantApp plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistantApp'] --- import observabilityAIAssistantAppObj from './observability_a_i_assistant_app.devdocs.json'; diff --git a/api_docs/observability_ai_assistant_management.mdx b/api_docs/observability_ai_assistant_management.mdx index 368830b966205..0a6cd4f656e10 100644 --- a/api_docs/observability_ai_assistant_management.mdx +++ b/api_docs/observability_ai_assistant_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAiAssistantManagement title: "observabilityAiAssistantManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAiAssistantManagement plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAiAssistantManagement'] --- import observabilityAiAssistantManagementObj from './observability_ai_assistant_management.devdocs.json'; diff --git a/api_docs/observability_logs_explorer.mdx b/api_docs/observability_logs_explorer.mdx index 509dc56ef16b8..3106ad25e10ba 100644 --- a/api_docs/observability_logs_explorer.mdx +++ b/api_docs/observability_logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogsExplorer title: "observabilityLogsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogsExplorer plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogsExplorer'] --- import observabilityLogsExplorerObj from './observability_logs_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index 47b27382ed39f..9c73c46efa49f 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index 9a7f818c21a99..f5e26915cb9b4 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 2656666b957d7..ac6690ba3a9dd 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index 31904a5a9443e..4324d1d11c14a 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 13c56f83dab90..80b6b3136a7d9 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 806 | 692 | 42 | +| 805 | 689 | 42 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 49119 | 239 | 37584 | 1875 | +| 49310 | 238 | 37600 | 1879 | ## Plugin Directory @@ -57,7 +57,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 271 | 0 | 252 | 1 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 129 | 0 | 123 | 12 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 54 | 0 | 51 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3194 | 31 | 2585 | 24 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3199 | 31 | 2590 | 24 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 8 | 0 | 8 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin provides the ability to create data views via a modal flyout inside Kibana apps | 35 | 0 | 25 | 5 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Reusable data view field editor across Kibana | 72 | 0 | 33 | 0 | @@ -101,7 +101,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 84 | 0 | 84 | 8 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 240 | 0 | 24 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 0 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1338 | 5 | 1216 | 72 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1339 | 5 | 1217 | 72 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 72 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -117,7 +117,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 4 | 0 | 4 | 0 | | inputControlVis | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Input Control visualization to Kibana | 0 | 0 | 0 | 0 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 127 | 2 | 100 | 4 | -| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | A simple example of how to use core's routing services test | 69 | 0 | 69 | 0 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | A simple example of how to use core's routing services test | 38 | 0 | 33 | 1 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides UI and APIs for the interactive setup mode. | 28 | 0 | 18 | 0 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 95 | 0 | 95 | 4 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | @@ -247,12 +247,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 33 | 0 | 33 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 237 | 0 | 223 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 73 | 0 | 73 | 2 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 98 | 0 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 1 | 0 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 19 | 0 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 23 | 0 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 19 | 0 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 1 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 18 | 0 | 18 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 4 | 0 | 4 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 49 | 0 | 49 | 8 | @@ -276,17 +271,18 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 217 | 0 | 180 | 9 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 79 | 0 | 50 | 9 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 24 | 0 | 24 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 144 | 3 | 141 | 20 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 146 | 2 | 142 | 20 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 8 | 4 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 8 | 0 | 8 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 8 | 0 | 8 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 10 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 48 | 0 | 32 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 30 | 0 | 30 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 195 | 1 | 128 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 0 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 101 | 0 | 0 | 0 | | | [@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) | - | 4 | 0 | 4 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 3 | 0 | 0 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 100 | 0 | 0 | 0 | | | [@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) | - | 5 | 0 | 5 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 103 | 0 | 27 | 0 | @@ -352,7 +348,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@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) | - | 54 | 7 | 54 | 6 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 13 | 0 | 13 | 1 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 488 | 2 | 193 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 489 | 2 | 193 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 92 | 0 | 79 | 10 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 44 | 0 | 43 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 2 | 0 | @@ -463,7 +459,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 51 | 0 | 51 | 1 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 14 | 0 | 9 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 80 | 0 | 80 | 1 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 1 | 0 | 0 | 0 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 5 | 0 | 4 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 44 | 0 | 43 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 7 | 0 | 7 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 5 | 0 | 5 | 0 | @@ -482,15 +478,16 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 102 | 0 | 86 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 15 | 0 | 9 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 38 | 2 | 33 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 114 | 0 | 88 | 0 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 120 | 0 | 94 | 1 | | | [@elastic/docs](https://github.com/orgs/elastic/teams/docs) | - | 77 | 0 | 77 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 5 | 0 | 5 | 1 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 41 | 0 | 27 | 6 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 152 | 0 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 33 | 0 | 24 | 1 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 13 | 0 | 5 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 35 | 0 | 34 | 0 | | | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 165 | 0 | 138 | 9 | -| | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 295 | 0 | 276 | 0 | +| | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 305 | 0 | 286 | 0 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 20 | 0 | 20 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 52 | 0 | 37 | 7 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 32 | 0 | 19 | 1 | @@ -498,9 +495,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 269 | 1 | 209 | 15 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 26 | 0 | 26 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 1 | 0 | -| | [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql) | - | 68 | 1 | 68 | 7 | +| | [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql) | - | 68 | 1 | 68 | 9 | | | [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql) | - | 53 | 0 | 51 | 0 | -| | [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql) | - | 194 | 0 | 184 | 10 | +| | [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql) | - | 189 | 0 | 178 | 10 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 39 | 0 | 39 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 52 | 0 | 52 | 1 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 39 | 0 | 14 | 1 | @@ -729,7 +726,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 39 | 0 | 25 | 1 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 86 | 0 | 86 | 1 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 42 | 0 | 28 | 0 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 56 | 0 | 47 | 0 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 55 | 0 | 46 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 9 | 0 | 8 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the unified data table which can be integrated into apps | 153 | 0 | 81 | 1 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 18 | 0 | 17 | 5 | @@ -745,5 +742,5 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 10 | 0 | 9 | 1 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 13 | 0 | 13 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 6 | 0 | 2 | 0 | -| | [@elastic/security-detection-rule-management](https://github.com/orgs/elastic/teams/security-detection-rule-management) | - | 18 | 0 | 9 | 0 | +| | [@elastic/security-detection-rule-management](https://github.com/orgs/elastic/teams/security-detection-rule-management) | - | 20 | 0 | 10 | 0 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index 55e27dddad02f..4df0ee0b57d97 100644 --- a/api_docs/presentation_panel.mdx +++ b/api_docs/presentation_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationPanel title: "presentationPanel" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationPanel plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 0cbb54c1599bc..7e59e1b428305 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 59843ba7bdd49..b03bdffd3b0d2 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index 5c2ba575a0824..e3310f1e571a0 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 5dd63fc0897b0..1b78a818df00f 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: 2024-06-18 +date: 2024-06-19 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 006a1a383fb19..10d2a95a204f3 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: 2024-06-18 +date: 2024-06-19 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 e82d752c9c713..3c7589a1dfaa4 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: 2024-06-18 +date: 2024-06-19 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 982b4f418e67b..f39c370de06fc 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: 2024-06-18 +date: 2024-06-19 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 cacdcf0747d1f..a046e09ac1206 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: 2024-06-18 +date: 2024-06-19 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 5fb36ebc0642e..2b3aebccf8f44 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: 2024-06-18 +date: 2024-06-19 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 df8d813489241..dfcabf012f816 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 71d04fa6f6d06..a4b75fa8bf8af 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: 2024-06-18 +date: 2024-06-19 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 0f855887386a8..997699a68579a 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: 2024-06-18 +date: 2024-06-19 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 0e2007a50b871..a353a4cff8bc9 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: 2024-06-18 +date: 2024-06-19 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 c65779a953eb0..5fe795374d9fd 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: 2024-06-18 +date: 2024-06-19 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 6061c6ce60372..8b0e1bbb43838 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: 2024-06-18 +date: 2024-06-19 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 41de4c90572e6..f8503be8f380b 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index e27f2058a1a4d..45a03aa097976 100644 --- a/api_docs/search_connectors.mdx +++ b/api_docs/search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchConnectors title: "searchConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the searchConnectors plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index 7c617046a080e..960e4e7e48960 100644 --- a/api_docs/search_inference_endpoints.mdx +++ b/api_docs/search_inference_endpoints.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchInferenceEndpoints title: "searchInferenceEndpoints" image: https://source.unsplash.com/400x175/?github description: API docs for the searchInferenceEndpoints plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index efc97cf266849..470c28d2868b4 100644 --- a/api_docs/search_notebooks.mdx +++ b/api_docs/search_notebooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNotebooks title: "searchNotebooks" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNotebooks plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNotebooks'] --- import searchNotebooksObj from './search_notebooks.devdocs.json'; diff --git a/api_docs/search_playground.mdx b/api_docs/search_playground.mdx index fd6257e783ef7..1f957baa893ee 100644 --- a/api_docs/search_playground.mdx +++ b/api_docs/search_playground.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchPlayground title: "searchPlayground" image: https://source.unsplash.com/400x175/?github description: API docs for the searchPlayground plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index d1327bb9f85f5..ad7fdca6c19f6 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 36c431192543d..659f8ee587527 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -485,7 +485,7 @@ "\nExperimental flag needed to enable the link" ], "signature": [ - "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"agentStatusClientEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"responseActionScanEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutDisabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"alertSuppressionForEsqlRuleEnabled\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineEnabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"perFieldPrebuiltRulesDiffingEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"aiAssistantFlyoutMode\" | \"valueListItemsModalEnabled\" | \"bulkCustomHighlightedFieldsEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | undefined" + "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"agentStatusClientEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"responseActionScanEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutDisabled\" | \"notesEnabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"alertSuppressionForEsqlRuleEnabled\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineEnabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"perFieldPrebuiltRulesDiffingEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"aiAssistantFlyoutMode\" | \"valueListItemsModalEnabled\" | \"bulkCustomHighlightedFieldsEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -565,7 +565,7 @@ "\nExperimental flag needed to disable the link. Opposite of experimentalKey" ], "signature": [ - "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"agentStatusClientEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"responseActionScanEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutDisabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"alertSuppressionForEsqlRuleEnabled\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineEnabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"perFieldPrebuiltRulesDiffingEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"aiAssistantFlyoutMode\" | \"valueListItemsModalEnabled\" | \"bulkCustomHighlightedFieldsEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | undefined" + "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"agentStatusClientEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"responseActionScanEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutDisabled\" | \"notesEnabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"alertSuppressionForEsqlRuleEnabled\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineEnabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"perFieldPrebuiltRulesDiffingEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"aiAssistantFlyoutMode\" | \"valueListItemsModalEnabled\" | \"bulkCustomHighlightedFieldsEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -1964,7 +1964,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly agentStatusClientEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly alertSuppressionForEsqlRuleEnabled: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineEnabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly perFieldPrebuiltRulesDiffingEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly aiAssistantFlyoutMode: boolean; readonly valueListItemsModalEnabled: boolean; readonly bulkCustomHighlightedFieldsEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; }" + "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly agentStatusClientEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutDisabled: boolean; readonly notesEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly alertSuppressionForEsqlRuleEnabled: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineEnabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly perFieldPrebuiltRulesDiffingEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly aiAssistantFlyoutMode: boolean; readonly valueListItemsModalEnabled: boolean; readonly bulkCustomHighlightedFieldsEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/types.ts", "deprecated": false, @@ -3071,7 +3071,7 @@ "\nThe security solution generic experimental features" ], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly agentStatusClientEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly alertSuppressionForEsqlRuleEnabled: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineEnabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly perFieldPrebuiltRulesDiffingEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly aiAssistantFlyoutMode: boolean; readonly valueListItemsModalEnabled: boolean; readonly bulkCustomHighlightedFieldsEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; }" + "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly agentStatusClientEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutDisabled: boolean; readonly notesEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly alertSuppressionForEsqlRuleEnabled: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineEnabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly perFieldPrebuiltRulesDiffingEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly aiAssistantFlyoutMode: boolean; readonly valueListItemsModalEnabled: boolean; readonly bulkCustomHighlightedFieldsEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/server/plugin_contract.ts", "deprecated": false, @@ -3247,7 +3247,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly agentStatusClientEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly alertSuppressionForEsqlRuleEnabled: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineEnabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly perFieldPrebuiltRulesDiffingEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly aiAssistantFlyoutMode: boolean; readonly valueListItemsModalEnabled: boolean; readonly bulkCustomHighlightedFieldsEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; }" + "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly agentStatusClientEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutDisabled: boolean; readonly notesEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly alertSuppressionForEsqlRuleEnabled: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineEnabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly perFieldPrebuiltRulesDiffingEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly aiAssistantFlyoutMode: boolean; readonly valueListItemsModalEnabled: boolean; readonly bulkCustomHighlightedFieldsEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, @@ -3313,7 +3313,7 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: false; readonly kubernetesEnabled: true; readonly donutChartEmbeddablesEnabled: false; readonly previewTelemetryUrlEnabled: false; readonly extendedRuleExecutionLoggingEnabled: false; readonly socTrendsEnabled: false; readonly responseActionsEnabled: true; readonly endpointResponseActionsEnabled: true; readonly responseActionUploadEnabled: true; readonly automatedProcessActionsEnabled: true; readonly responseActionsSentinelOneV1Enabled: true; readonly responseActionsSentinelOneV2Enabled: true; readonly responseActionsSentinelOneGetFileEnabled: false; readonly agentStatusClientEnabled: false; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: false; readonly responseActionScanEnabled: false; readonly alertsPageChartsEnabled: true; readonly alertTypeEnabled: false; readonly expandableFlyoutDisabled: false; readonly assistantModelEvaluation: false; readonly assistantKnowledgeBaseByDefault: false; readonly newUserDetailsFlyoutManagedUser: false; readonly riskScoringPersistence: true; readonly riskScoringRoutesEnabled: true; readonly esqlRulesDisabled: false; readonly protectionUpdatesEnabled: true; readonly disableTimelineSaveTour: false; readonly alertSuppressionForEsqlRuleEnabled: false; readonly riskEnginePrivilegesRouteEnabled: true; readonly sentinelOneDataInAnalyzerEnabled: true; readonly sentinelOneManualHostActionsEnabled: true; readonly crowdstrikeDataInAnalyzerEnabled: false; readonly jamfDataInAnalyzerEnabled: false; readonly jsonPrebuiltRulesDiffingEnabled: true; readonly timelineEsqlTabDisabled: false; readonly unifiedComponentsInTimelineEnabled: false; readonly analyzerDatePickersAndSourcererDisabled: false; readonly perFieldPrebuiltRulesDiffingEnabled: true; readonly malwareOnWriteScanOptionAvailable: true; readonly unifiedManifestEnabled: false; readonly aiAssistantFlyoutMode: true; readonly valueListItemsModalEnabled: true; readonly bulkCustomHighlightedFieldsEnabled: false; readonly manualRuleRunEnabled: false; readonly filterProcessDescendantsForEventFiltersEnabled: false; }" + "{ readonly excludePoliciesInFilterEnabled: false; readonly kubernetesEnabled: true; readonly donutChartEmbeddablesEnabled: false; readonly previewTelemetryUrlEnabled: false; readonly extendedRuleExecutionLoggingEnabled: false; readonly socTrendsEnabled: false; readonly responseActionsEnabled: true; readonly endpointResponseActionsEnabled: true; readonly responseActionUploadEnabled: true; readonly automatedProcessActionsEnabled: true; readonly responseActionsSentinelOneV1Enabled: true; readonly responseActionsSentinelOneV2Enabled: true; readonly responseActionsSentinelOneGetFileEnabled: false; readonly agentStatusClientEnabled: false; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: false; readonly responseActionScanEnabled: false; readonly alertsPageChartsEnabled: true; readonly alertTypeEnabled: false; readonly expandableFlyoutDisabled: false; readonly notesEnabled: false; readonly assistantModelEvaluation: false; readonly assistantKnowledgeBaseByDefault: false; readonly newUserDetailsFlyoutManagedUser: false; readonly riskScoringPersistence: true; readonly riskScoringRoutesEnabled: true; readonly esqlRulesDisabled: false; readonly protectionUpdatesEnabled: true; readonly disableTimelineSaveTour: false; readonly alertSuppressionForEsqlRuleEnabled: false; readonly riskEnginePrivilegesRouteEnabled: true; readonly sentinelOneDataInAnalyzerEnabled: true; readonly sentinelOneManualHostActionsEnabled: true; readonly crowdstrikeDataInAnalyzerEnabled: false; readonly jamfDataInAnalyzerEnabled: false; readonly jsonPrebuiltRulesDiffingEnabled: true; readonly timelineEsqlTabDisabled: false; readonly unifiedComponentsInTimelineEnabled: false; readonly analyzerDatePickersAndSourcererDisabled: false; readonly perFieldPrebuiltRulesDiffingEnabled: true; readonly malwareOnWriteScanOptionAvailable: true; readonly unifiedManifestEnabled: false; readonly aiAssistantFlyoutMode: true; readonly valueListItemsModalEnabled: true; readonly bulkCustomHighlightedFieldsEnabled: false; readonly manualRuleRunEnabled: false; readonly filterProcessDescendantsForEventFiltersEnabled: false; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 09fd66a8fa53b..10fb34dfcd75a 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index da3e0b614f45b..c96d7a20b5e9f 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index 4dfe48856ba18..7acea530f5fc5 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 2b167cbb92301..1eb61bcf6de72 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index 0a361ed9f29d4..c403796a2f280 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index e48d941822de4..c882d39ee8c64 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index dc8c512217b73..39e2308ac3b35 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: 2024-06-18 +date: 2024-06-19 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 65f4bf5340d47..0955b3e6997b2 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index 4615111556016..8bb7ffb38c2ea 100644 --- a/api_docs/slo.mdx +++ b/api_docs/slo.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/slo title: "slo" image: https://source.unsplash.com/400x175/?github description: API docs for the slo plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'slo'] --- import sloObj from './slo.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 895059ad9b055..359079def7dbc 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.devdocs.json b/api_docs/spaces.devdocs.json index 0d6cb86b49fa4..b19ac58371016 100644 --- a/api_docs/spaces.devdocs.json +++ b/api_docs/spaces.devdocs.json @@ -1793,7 +1793,14 @@ "\nSolution selected for this space." ], "signature": [ - "\"search\" | \"security\" | \"observability\" | \"classic\" | undefined" + { + "pluginId": "cloud", + "scope": "common", + "docId": "kibCloudPluginApi", + "section": "def-common.OnBoardingDefaultSolution", + "text": "OnBoardingDefaultSolution" + }, + " | \"classic\" | undefined" ], "path": "x-pack/plugins/spaces/common/types/space/v1.ts", "deprecated": false, @@ -1825,7 +1832,15 @@ "The space to represent with an avatar." ], "signature": [ - "{ id?: string | undefined; name?: string | undefined; description?: string | undefined; color?: string | undefined; initials?: string | undefined; imageUrl?: string | undefined; disabledFeatures?: string[] | undefined; _reserved?: boolean | undefined; solution?: \"search\" | \"security\" | \"observability\" | \"classic\" | undefined; }" + "{ id?: string | undefined; name?: string | undefined; description?: string | undefined; color?: string | undefined; initials?: string | undefined; imageUrl?: string | undefined; disabledFeatures?: string[] | undefined; _reserved?: boolean | undefined; solution?: ", + { + "pluginId": "cloud", + "scope": "common", + "docId": "kibCloudPluginApi", + "section": "def-common.OnBoardingDefaultSolution", + "text": "OnBoardingDefaultSolution" + }, + " | \"classic\" | undefined; }" ], "path": "x-pack/plugins/spaces/public/space_avatar/types.ts", "deprecated": false, @@ -3701,7 +3716,14 @@ "\nSolution selected for this space." ], "signature": [ - "\"search\" | \"security\" | \"observability\" | \"classic\" | undefined" + { + "pluginId": "cloud", + "scope": "common", + "docId": "kibCloudPluginApi", + "section": "def-common.OnBoardingDefaultSolution", + "text": "OnBoardingDefaultSolution" + }, + " | \"classic\" | undefined" ], "path": "x-pack/plugins/spaces/common/types/space/v1.ts", "deprecated": false, @@ -4951,7 +4973,14 @@ "\nSolution selected for this space." ], "signature": [ - "\"search\" | \"security\" | \"observability\" | \"classic\" | undefined" + { + "pluginId": "cloud", + "scope": "common", + "docId": "kibCloudPluginApi", + "section": "def-common.OnBoardingDefaultSolution", + "text": "OnBoardingDefaultSolution" + }, + " | \"classic\" | undefined" ], "path": "x-pack/plugins/spaces/common/types/space/v1.ts", "deprecated": false, diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index e9f21582eff65..385368b87f654 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: 2024-06-18 +date: 2024-06-19 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 3737d2302fe6b..3314b5bb8aa63 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.devdocs.json b/api_docs/stack_connectors.devdocs.json index 435af06ccdd6b..447872c4249ed 100644 --- a/api_docs/stack_connectors.devdocs.json +++ b/api_docs/stack_connectors.devdocs.json @@ -186,7 +186,7 @@ }, "; }>" ], - "path": "x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts", + "path": "x-pack/plugins/stack_connectors/server/connector_types/webhook/schema.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 6b67580e44db9..086640353d71c 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: 2024-06-18 +date: 2024-06-19 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 f49b7846ed095..03645e34e324d 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: 2024-06-18 +date: 2024-06-19 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 178ea146c56ba..2c751b121ed49 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: 2024-06-18 +date: 2024-06-19 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 2a237ce79ed09..51d70a87ff4b4 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: 2024-06-18 +date: 2024-06-19 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 c35b4097e77e8..176820c472d6f 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: 2024-06-18 +date: 2024-06-19 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 444de09aa6b4a..ce2e6eb5c50d8 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index 2b06f627d6f2d..7426e2bcc3ed3 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 5b74a01369404..5e6c067200b75 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: 2024-06-18 +date: 2024-06-19 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 bcb9dba7866d9..0fbca32935a9a 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: 2024-06-18 +date: 2024-06-19 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 76563f3a7636a..c283e9cbb1940 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: 2024-06-18 +date: 2024-06-19 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 a82268cb54719..947d503130b72 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: 2024-06-18 +date: 2024-06-19 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 dc674fa70fdf7..9927f905c3232 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: 2024-06-18 +date: 2024-06-19 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 953b01ceadd39..f0c965a6d86fd 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index d738743a9477e..797100653e885 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 2454d26694b22..673a04e07caa2 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.devdocs.json b/api_docs/unified_search.devdocs.json index 3a6a417a835bd..9a084801174c4 100644 --- a/api_docs/unified_search.devdocs.json +++ b/api_docs/unified_search.devdocs.json @@ -1593,9 +1593,9 @@ "signature": [ "{ optIn: (optInConfig: ", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.OptInConfig", "text": "OptInConfig" }, @@ -1603,9 +1603,9 @@ "Observable", "<", { - "pluginId": "@kbn/analytics-client", + "pluginId": "@kbn/ebt", "scope": "common", - "docId": "kibKbnAnalyticsClientPluginApi", + "docId": "kibKbnEbtPluginApi", "section": "def-common.TelemetryCounter", "text": "TelemetryCounter" }, diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 6ddb906f1436a..da150ddd187d5 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: 2024-06-18 +date: 2024-06-19 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 7d9046ef2e02b..3828629b7de40 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index 35f9262187c03..8b9feb48b2554 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index d15b383e344da..64a832b6cff6c 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.devdocs.json b/api_docs/usage_collection.devdocs.json index b573f8c8d3d7e..609cbc0a5a633 100644 --- a/api_docs/usage_collection.devdocs.json +++ b/api_docs/usage_collection.devdocs.json @@ -1869,7 +1869,7 @@ "signature": [ "\"boolean\" | \"keyword\" | \"text\" | \"date\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"double\"" ], - "path": "packages/analytics/client/src/schema/types.ts", + "path": "packages/analytics/ebt/client/src/schema/types.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 8d1371644bd4d..436db094913ba 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: 2024-06-18 +date: 2024-06-19 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 aa257292348cd..6101ac7d027d2 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: 2024-06-18 +date: 2024-06-19 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 4c024378c51a5..890eb0c990a2e 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: 2024-06-18 +date: 2024-06-19 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 984c102379604..6aff52a01cd88 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: 2024-06-18 +date: 2024-06-19 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 de21d886b7c46..dca9fa99c07b0 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: 2024-06-18 +date: 2024-06-19 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 ee4144f629efe..6f52c4d6726a1 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: 2024-06-18 +date: 2024-06-19 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 0cd0162750577..c984f1e20a831 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: 2024-06-18 +date: 2024-06-19 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 59414d94e8ed8..3dce4637737ae 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: 2024-06-18 +date: 2024-06-19 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 d9f9590acbe69..1106d22596c13 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: 2024-06-18 +date: 2024-06-19 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 30af10196561f..d899070ea869f 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: 2024-06-18 +date: 2024-06-19 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 5c5f8367dc6b9..89682e5f50528 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: 2024-06-18 +date: 2024-06-19 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 0ca9f2fe7118c..4ae390b8e9a7c 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: 2024-06-18 +date: 2024-06-19 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 1176ba240c38e..862c90efea645 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: 2024-06-18 +date: 2024-06-19 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From dbdc797781273eb9387744b5b9da3dfc7b6e8a5c Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Wed, 19 Jun 2024 10:15:05 +0200 Subject: [PATCH 098/127] Prevent write blocking target index during reindex migration (#185939) ## Summary Addresses https://github.com/elastic/kibana/issues/185918 The idea is to simply check whether the index that a migrator is trying to `write_block` (aka the source of the reindex operation) matches the target index name. In this case: * We assume that other migrators are half way through, ahead of us. * We abort operation and trust other instances' migrators to finish the job. * Subsequent restart, when migration has finished, should basically be a no-op. --- .../src/actions/clone_index.ts | 2 +- .../src/actions/create_index.ts | 2 +- .../src/actions/index.ts | 9 ++++ .../src/actions/initialize_action.ts | 2 +- .../src/actions/safe_write_block.test.ts | 54 +++++++++++++++++++ .../src/actions/safe_write_block.ts | 47 ++++++++++++++++ .../src/actions/update_and_pickup_mappings.ts | 2 +- .../update_source_mappings_properties.ts | 2 +- .../src/model/model.test.ts | 9 ++++ .../src/model/model.ts | 8 +++ .../src/next.ts | 6 ++- 11 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.test.ts create mode 100644 packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.ts diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts index 7334f17191df0..2271a2773cfab 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts @@ -8,7 +8,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import { pipe } from 'fp-ts/lib/pipeable'; +import { pipe } from 'fp-ts/lib/function'; import { errors as EsErrors } from '@elastic/elasticsearch'; import type { ElasticsearchClient, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts index aea970f1bf5f9..0b38f9c369d5f 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts @@ -8,7 +8,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import { pipe } from 'fp-ts/lib/pipeable'; +import { pipe } from 'fp-ts/lib/function'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient, 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 79df66c4b9ccb..84f37c96cca5f 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 @@ -27,6 +27,9 @@ export { initAction } from './initialize_action'; export type { FetchIndexResponse, FetchIndicesParams } from './fetch_indices'; export { fetchIndices } from './fetch_indices'; +export type { SafeWriteBlockParams } from './safe_write_block'; +export { safeWriteBlock } from './safe_write_block'; + export type { SetWriteBlockParams } from './set_write_block'; export { setWriteBlock } from './set_write_block'; @@ -158,6 +161,11 @@ export interface EsResponseTooLargeError { contentLength: number; } +export interface SourceEqualsTarget { + type: 'source_equals_target'; + index: string; +} + /** @internal */ export interface AcknowledgeResponse { acknowledged: boolean; @@ -185,6 +193,7 @@ export interface ActionErrorTypeMap { index_mappings_incomplete: IndexMappingsIncomplete; types_changed: TypesChanged; operation_not_supported: OperationNotSupported; + source_equals_target: SourceEqualsTarget; } /** diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts index 8daa548039eeb..7db32f7a67d99 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts @@ -8,7 +8,7 @@ import * as TaskEither from 'fp-ts/lib/TaskEither'; import * as Either from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; +import { pipe } from 'fp-ts/lib/function'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { catchRetryableEsClientErrors, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.test.ts new file mode 100644 index 0000000000000..40e60a7afd4c4 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import * as Either from 'fp-ts/lib/Either'; +import * as TaskEither from 'fp-ts/lib/TaskEither'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { safeWriteBlock } from './safe_write_block'; + +jest.mock('./set_write_block'); +import { setWriteBlock } from './set_write_block'; + +const setWriteBlockMock = setWriteBlock as jest.MockedFn; + +describe('safeWriteBlock', () => { + beforeEach(() => { + setWriteBlockMock.mockReset(); + setWriteBlockMock.mockReturnValueOnce( + TaskEither.fromEither(Either.right('set_write_block_succeeded' as const)) + ); + }); + + const client = elasticsearchClientMock.createInternalClient(); + it('returns a Left response if source and target indices match', async () => { + const task = safeWriteBlock({ + client, + sourceIndex: '.kibana_8.15.0_001', + targetIndex: '.kibana_8.15.0_001', + }); + const res = await task(); + expect(res).toEqual(Either.left({ type: 'source_equals_target', index: '.kibana_8.15.0_001' })); + expect(setWriteBlockMock).not.toHaveBeenCalled(); + }); + + it('calls setWriteBlock if indices are different', async () => { + const task = safeWriteBlock({ + client, + sourceIndex: '.kibana_7.13.0_001', + targetIndex: '.kibana_8.15.0_001', + timeout: '28s', + }); + const res = await task(); + expect(res).toEqual(Either.right('set_write_block_succeeded' as const)); + expect(setWriteBlockMock).toHaveBeenCalledTimes(1); + expect(setWriteBlockMock).toHaveBeenCalledWith({ + client, + index: '.kibana_7.13.0_001', + timeout: '28s', + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.ts new file mode 100644 index 0000000000000..cb1270428f5dd --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/safe_write_block.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { RetryableEsClientError } from './catch_retryable_es_client_errors'; +import { DEFAULT_TIMEOUT, type SourceEqualsTarget, type IndexNotFound } from '.'; +import { setWriteBlock } from './set_write_block'; + +/** @internal */ +export interface SafeWriteBlockParams { + client: ElasticsearchClient; + sourceIndex: string; + targetIndex: string; + timeout?: string; +} + +export const safeWriteBlock = ({ + client, + sourceIndex, + targetIndex, + timeout = DEFAULT_TIMEOUT, +}: SafeWriteBlockParams): TaskEither.TaskEither< + SourceEqualsTarget | IndexNotFound | RetryableEsClientError, + 'set_write_block_succeeded' +> => { + const assertSourceAndTargetDifferTask: TaskEither.TaskEither< + SourceEqualsTarget, + 'source_and_target_differ' + > = TaskEither.fromEither( + sourceIndex === targetIndex + ? Either.left({ type: 'source_equals_target' as const, index: sourceIndex }) + : Either.right('source_and_target_differ' as const) + ); + + return pipe( + assertSourceAndTargetDifferTask, + TaskEither.chainW(() => setWriteBlock({ client, index: sourceIndex, timeout })) + ); +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts index 8478ad08247a5..9cd55f88a066c 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts @@ -8,7 +8,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import { pipe } from 'fp-ts/lib/pipeable'; +import { pipe } from 'fp-ts/lib/function'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import type { IndexMapping } from '@kbn/core-saved-objects-base-server-internal'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_source_mappings_properties.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_source_mappings_properties.ts index 3a73f948efa20..1a47992074af8 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_source_mappings_properties.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_source_mappings_properties.ts @@ -8,7 +8,7 @@ import { omit } from 'lodash'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import { pipe } from 'fp-ts/lib/pipeable'; +import { pipe } from 'fp-ts/lib/function'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import type { IndexMapping, VirtualVersionMap } from '@kbn/core-saved-objects-base-server-internal'; import { diffMappings } from '../core/diff_mappings'; 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 f06e9f836f2c5..1980a6e6128db 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 @@ -1645,6 +1645,15 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('SET_SOURCE_WRITE_BLOCK -> REFRESH_TARGET if source index matches target index', () => { + const index = `.kibana_${setWriteBlockState.kibanaVersion}_001`; + const res: ResponseType<'SET_SOURCE_WRITE_BLOCK'> = Either.left({ + type: 'source_equals_target' as const, + index, + }); + const newState = model(setWriteBlockState, res); + expect(newState.controlState).toEqual('REFRESH_TARGET'); + }); }); describe('CALCULATE_EXCLUDE_FILTERS', () => { 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 e25d48af4ed25..4f1f48444dc23 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 @@ -736,6 +736,14 @@ export const model = (currentState: State, resW: ResponseType): ...stateP, controlState: 'CALCULATE_EXCLUDE_FILTERS', }; + } else if (isTypeof(res.left, 'source_equals_target')) { + // As part of a reindex-migration, we wanted to block the source index to prevent updates + // However, this migrator's source index matches the target index. + // Thus, another instance's migrator is ahead of us. We skip the clone steps and continue the flow + return { + ...stateP, + controlState: 'REFRESH_TARGET', + }; } else if (isTypeof(res.left, 'index_not_found_exception')) { // We don't handle the following errors as the migration algorithm // will never cause them to occur: 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 9cd7f92ee4355..9f7da4a10c2e8 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 @@ -125,7 +125,11 @@ export const nextActionMap = ( knownTypes: state.knownTypes, }), SET_SOURCE_WRITE_BLOCK: (state: SetSourceWriteBlockState) => - Actions.setWriteBlock({ client, index: state.sourceIndex.value }), + Actions.safeWriteBlock({ + client, + sourceIndex: state.sourceIndex.value, + targetIndex: state.targetIndex, + }), CALCULATE_EXCLUDE_FILTERS: (state: CalculateExcludeFiltersState) => Actions.calculateExcludeFilters({ client, From 52e678a0aa95d5770fe1338d9f1475251499d346 Mon Sep 17 00:00:00 2001 From: jennypavlova Date: Wed, 19 Jun 2024 10:56:43 +0200 Subject: [PATCH 099/127] [Infra] Logs tab in container views should use container id (#186393) Closes #186392 ## Summary This PR fixes a bug with the Logs Tab in asset details using asset name instead of id. https://github.com/elastic/kibana/assets/14139027/19d4531c-fd9f-4327-ae2c-438fdcbb91f1 ## Testing - Check the logs tab in the asset details view for a container - Check the Open in Logs Stream link - It should show `container.id: {container.id}` as filter image - Check the logs tab in the asset details view for a host - Check the Open in Logs Stream link - It should show `host.name: {host.name}` as filter image --- .../public/components/asset_details/tabs/logs/logs.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/logs/logs.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/logs/logs.tsx index a8236069fe3a7..72ad37ce1cfda 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/logs/logs.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/logs/logs.tsx @@ -60,7 +60,7 @@ export const Logs = () => { const filter = useMemo(() => { const query = [ - `${findInventoryFields(asset.type).id}: "${asset.name}"`, + `${findInventoryFields(asset.type).id}: "${asset.id}"`, ...(textQueryDebounced !== '' ? [textQueryDebounced] : []), ].join(' and '); @@ -68,7 +68,7 @@ export const Logs = () => { language: 'kuery', query, }; - }, [asset.type, asset.name, textQueryDebounced]); + }, [asset.type, asset.id, textQueryDebounced]); const onQueryChange = useCallback((e: React.ChangeEvent) => { setTextQuery(e.target.value); @@ -82,12 +82,12 @@ export const Logs = () => { const logsUrl = useMemo(() => { return nodeLogsLocator.getRedirectUrl({ nodeField: findInventoryFields(asset.type).id, - nodeId: asset.name, + nodeId: asset.id, time: state.startTimestamp, filter: textQueryDebounced, logView, }); - }, [nodeLogsLocator, asset.name, asset.type, state.startTimestamp, textQueryDebounced, logView]); + }, [nodeLogsLocator, asset.id, asset.type, state.startTimestamp, textQueryDebounced, logView]); return ( From 85f67dd39ae7b4a3f8b96bdf8a3d421b67f6f45f Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 19 Jun 2024 11:04:33 +0200 Subject: [PATCH 100/127] Implement `elasticsearch.maxResponseSize` config option (#186291) ## Summary Fix https://github.com/elastic/kibana/issues/185042 - Add a new `elasticsearch.maxResponseSize` config option - Set this value to `100mb` on our serverless configuration file --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- config/serverless.yml | 3 + docs/setup/settings.asciidoc | 4 + .../src/client_config.test.ts | 24 +++++ .../src/client_config.ts | 5 ++ .../src/create_transport.test.ts | 73 +++++++++++++++ .../src/create_transport.ts | 14 +++ .../src/log_query_and_deprecation.test.ts | 37 ++++++++ .../src/log_query_and_deprecation.ts | 17 +++- .../tsconfig.json | 1 + .../src/elasticsearch_config.test.ts | 15 ++++ .../src/elasticsearch_config.ts | 17 +++- .../src/client/client_config.ts | 2 + .../core-elasticsearch-server/tsconfig.json | 3 +- packages/kbn-es-errors/index.ts | 7 +- packages/kbn-es-errors/src/errors.test.ts | 40 ++++++++- packages/kbn-es-errors/src/errors.ts | 14 +++ .../max_response_size_logging.test.ts | 89 +++++++++++++++++++ .../plugins/monitoring/server/config.test.ts | 1 + 18 files changed, 359 insertions(+), 7 deletions(-) create mode 100644 src/core/server/integration_tests/elasticsearch/max_response_size_logging.test.ts diff --git a/config/serverless.yml b/config/serverless.yml index cb4bbac7c92fa..6658eba7095c1 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -70,6 +70,9 @@ core.lifecycle.disablePreboot: true # Enable ZDT migration algorithm migrations.algorithm: zdt +# Enable elasticsearch response size circuit breaker +elasticsearch.maxResponseSize: "100mb" + # Limit batch size to reduce possibility of failures. # A longer migration time is acceptable due to the ZDT algorithm. migrations.batchSize: 250 diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 4405b746ca34f..cb096ec127154 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -89,6 +89,10 @@ configuration is effectively ignored when <> is enable The maximum number of sockets that can be used for communications with {es}. *Default: `Infinity`* +[[elasticsearch-maxResponseSize]] `elasticsearch.maxResponseSize`:: +Either `false` or a `byteSize` value. When set, responses from {es} with a size higher than the defined limit will be rejected. +This is intended to be used as a circuit-breaker mechanism to avoid memory errors in case of unexpectedly high responses coming from {es}. +*Default: `false`* [[elasticsearch-maxIdleSockets]] `elasticsearch.maxIdleSockets`:: The maximum number of idle sockets to keep open between {kib} and {es}. If more sockets become idle, they will be closed. diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.test.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.test.ts index b6526cc201717..de0702b62aa66 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.test.ts @@ -7,6 +7,7 @@ */ import { duration } from 'moment'; +import { ByteSizeValue } from '@kbn/config-schema'; import type { ElasticsearchClientConfig } from '@kbn/core-elasticsearch-server'; import { parseClientOptions } from './client_config'; import { getDefaultHeaders } from './headers'; @@ -19,6 +20,7 @@ const createConfig = ( compression: false, maxSockets: Infinity, maxIdleSockets: 300, + maxResponseSize: undefined, idleSocketTimeout: duration(30, 'seconds'), sniffOnStart: false, sniffOnConnectionFault: false, @@ -152,6 +154,28 @@ describe('parseClientOptions', () => { }); }); + describe('`maxResponseSize` option', () => { + it('does not set the values on client options when undefined', () => { + const options = parseClientOptions( + createConfig({ maxResponseSize: undefined }), + false, + kibanaVersion + ); + expect(options.maxResponseSize).toBe(undefined); + expect(options.maxCompressedResponseSize).toBe(undefined); + }); + + it('sets the right values on client options when defined', () => { + const options = parseClientOptions( + createConfig({ maxResponseSize: ByteSizeValue.parse('2kb') }), + false, + kibanaVersion + ); + expect(options.maxResponseSize).toBe(2048); + expect(options.maxCompressedResponseSize).toBe(2048); + }); + }); + describe('`compression` option', () => { it('`compression` is true', () => { const options = parseClientOptions( diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.ts index 58660a9917348..7310cdc2da7cd 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/client_config.ts @@ -47,6 +47,11 @@ export function parseClientOptions( compression: config.compression, }; + if (config.maxResponseSize) { + clientOptions.maxResponseSize = config.maxResponseSize.getValueInBytes(); + clientOptions.maxCompressedResponseSize = config.maxResponseSize.getValueInBytes(); + } + if (config.pingTimeout != null) { clientOptions.pingTimeout = getDurationAsMs(config.pingTimeout); } diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.test.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.test.ts index ce54d8356f38b..3039119ae3c16 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.test.ts @@ -265,6 +265,79 @@ describe('createTransport', () => { ); }); }); + + describe('maxResponseSize options', () => { + it('does not set values when not provided in the options', async () => { + const transportClass = createTransportClass(); + const transport = new transportClass(baseConstructorParams); + const requestParams = { method: 'GET', path: '/' }; + + await transport.request(requestParams, {}); + + expect(transportRequestMock).toHaveBeenCalledTimes(1); + expect(transportRequestMock).toHaveBeenCalledWith( + expect.any(Object), + expect.not.objectContaining({ + maxResponseSize: expect.any(Number), + maxCompressedResponseSize: expect.any(Number), + }) + ); + }); + + it('uses `maxResponseSize` from the options when provided and when `maxCompressedResponseSize` is not', async () => { + const transportClass = createTransportClass(); + const transport = new transportClass(baseConstructorParams); + const requestParams = { method: 'GET', path: '/' }; + + await transport.request(requestParams, { maxResponseSize: 234 }); + + expect(transportRequestMock).toHaveBeenCalledTimes(1); + expect(transportRequestMock).toHaveBeenCalledWith( + expect.any(Object), + expect.objectContaining({ + maxResponseSize: 234, + maxCompressedResponseSize: 234, + }) + ); + }); + + it('uses `maxCompressedResponseSize` from the options when provided and when `maxResponseSize` is not', async () => { + const transportClass = createTransportClass(); + const transport = new transportClass(baseConstructorParams); + const requestParams = { method: 'GET', path: '/' }; + + await transport.request(requestParams, { maxCompressedResponseSize: 272 }); + + expect(transportRequestMock).toHaveBeenCalledTimes(1); + expect(transportRequestMock).toHaveBeenCalledWith( + expect.any(Object), + expect.objectContaining({ + maxResponseSize: 272, + maxCompressedResponseSize: 272, + }) + ); + }); + + it('uses individual values when both `maxResponseSize` and `maxCompressedResponseSize` are defined', async () => { + const transportClass = createTransportClass(); + const transport = new transportClass(baseConstructorParams); + const requestParams = { method: 'GET', path: '/' }; + + await transport.request(requestParams, { + maxResponseSize: 512, + maxCompressedResponseSize: 272, + }); + + expect(transportRequestMock).toHaveBeenCalledTimes(1); + expect(transportRequestMock).toHaveBeenCalledWith( + expect.any(Object), + expect.objectContaining({ + maxResponseSize: 512, + maxCompressedResponseSize: 272, + }) + ); + }); + }); }); describe('unauthorized error handler', () => { diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.ts index 07ed3833a7af2..ef643faa05c17 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/create_transport.ts @@ -41,6 +41,20 @@ export const createTransport = ({ async request(params: TransportRequestParams, options?: TransportRequestOptions) { const opts: TransportRequestOptions = options ? { ...options } : {}; + // sync override of maxResponseSize and maxCompressedResponseSize + if (options) { + if ( + options.maxResponseSize !== undefined && + options.maxCompressedResponseSize === undefined + ) { + opts.maxCompressedResponseSize = options.maxResponseSize; + } else if ( + options.maxCompressedResponseSize !== undefined && + options.maxResponseSize === undefined + ) { + opts.maxResponseSize = options.maxCompressedResponseSize; + } + } const opaqueId = getExecutionContext(); if (opaqueId && !opts.opaqueId) { // rewrites headers['x-opaque-id'] if it presents diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts index edb3ab90e6bc6..e974951da8aef 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts @@ -1051,4 +1051,41 @@ describe('instrumentQueryAndDeprecationLogger', () => { }); }); }); + + describe('requests aborted due to maximum response size exceeded errors', () => { + const requestAbortedErrorMessage = `The content length (9000) is bigger than the maximum allowed buffer (42)`; + + it('logs warning when the client emits a RequestAbortedError error due to excessive response length ', () => { + instrumentEsQueryAndDeprecationLogger({ + logger, + client, + type: 'test type', + apisToRedactInLogs: [], + }); + + client.diagnostic.emit( + 'response', + new errors.RequestAbortedError(requestAbortedErrorMessage), + null + ); + + expect(loggingSystemMock.collect(logger).warn[0][0]).toMatchInlineSnapshot( + `"Request was aborted: The content length (9000) is bigger than the maximum allowed buffer (42)"` + ); + }); + + it('does not log warning for other type of errors', () => { + instrumentEsQueryAndDeprecationLogger({ + logger, + client, + type: 'test type', + apisToRedactInLogs: [], + }); + + const response = createApiResponse({ body: {} }); + client.diagnostic.emit('response', new errors.TimeoutError('message', response), response); + + expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(`Array []`); + }); + }); }); diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts index 8d7f0f0a5c2dd..753b17a6a7aa3 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts @@ -12,7 +12,7 @@ import { stringify } from 'querystring'; import { errors, DiagnosticResult, RequestBody, Client } from '@elastic/elasticsearch'; import numeral from '@elastic/numeral'; import type { Logger } from '@kbn/logging'; -import type { ElasticsearchErrorDetails } from '@kbn/es-errors'; +import { isMaximumResponseSizeExceededError, type ElasticsearchErrorDetails } from '@kbn/es-errors'; import type { ElasticsearchApiToRedactInLogs } from '@kbn/core-elasticsearch-server'; import { getEcsResponseLog } from './get_ecs_response_log'; @@ -171,6 +171,16 @@ function getQueryMessage( } } +function getResponseSizeExceededErrorMessage(error: errors.RequestAbortedError): string { + if (error.meta) { + const params = error.meta.meta.request.params; + return `Request against ${params.method} ${params.path} was aborted: ${error.message}`; + } else { + // in theory meta is always populated for such errors, but better safe than sorry + return `Request was aborted: ${error.message}`; + } +} + export const instrumentEsQueryAndDeprecationLogger = ({ logger, client, @@ -184,6 +194,7 @@ export const instrumentEsQueryAndDeprecationLogger = ({ }) => { const queryLogger = logger.get('query', type); const deprecationLogger = logger.get('deprecation'); + const warningLogger = logger.get('warnings'); // elasticsearch.warnings client.diagnostic.on('response', (error, event) => { // we could check this once and not subscribe to response events if both are disabled, @@ -191,6 +202,10 @@ export const instrumentEsQueryAndDeprecationLogger = ({ const logQuery = queryLogger.isLevelEnabled('debug'); const logDeprecation = deprecationLogger.isLevelEnabled('debug'); + if (error && isMaximumResponseSizeExceededError(error)) { + warningLogger.warn(getResponseSizeExceededErrorMessage(error)); + } + if (event && (logQuery || logDeprecation)) { const bytes = getContentLength(event.headers); const queryMsg = getQueryMessage(bytes, error, event, apisToRedactInLogs); diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/tsconfig.json b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/tsconfig.json index 2288caa55dea8..de4169d034e65 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/tsconfig.json +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/tsconfig.json @@ -22,6 +22,7 @@ "@kbn/core-logging-server-mocks", "@kbn/core-http-server-mocks", "@kbn/core-metrics-server", + "@kbn/config-schema", ], "exclude": [ "target/**/*", diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.test.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.test.ts index 58745a0e85d09..cafa50e65d91c 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.test.ts @@ -42,6 +42,7 @@ test('set correct defaults', () => { "idleSocketTimeout": "PT1M", "ignoreVersionMismatch": false, "maxIdleSockets": 256, + "maxResponseSize": undefined, "maxSockets": 800, "password": undefined, "pingTimeout": "PT30S", @@ -127,6 +128,20 @@ describe('#maxSockets', () => { }); }); +describe('#maxResponseSize', () => { + test('accepts `false` value', () => { + const configValue = new ElasticsearchConfig(config.schema.validate({ maxResponseSize: false })); + expect(configValue.maxResponseSize).toBe(undefined); + }); + + test('accepts bytesize value', () => { + const configValue = new ElasticsearchConfig( + config.schema.validate({ maxResponseSize: '200b' }) + ); + expect(configValue.maxResponseSize!.getValueInBytes()).toBe(200); + }); +}); + test('#requestHeadersWhitelist accepts both string and array of strings', () => { let configValue = new ElasticsearchConfig( config.schema.validate({ requestHeadersWhitelist: 'token' }) diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts index 1f6d75b2f30e1..010bc3ac1c796 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema'; +import { readFileSync } from 'fs'; +import { Duration } from 'moment'; import { readPkcs12Keystore, readPkcs12Truststore } from '@kbn/crypto'; import { i18n } from '@kbn/i18n'; -import { Duration } from 'moment'; -import { readFileSync } from 'fs'; +import { schema, offeringBasedSchema, ByteSizeValue, type TypeOf } from '@kbn/config-schema'; import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal'; import type { ConfigDeprecationProvider } from '@kbn/config'; import type { @@ -42,6 +42,9 @@ export const configSchema = schema.object({ }), maxSockets: schema.number({ defaultValue: 800, min: 1 }), maxIdleSockets: schema.number({ defaultValue: 256, min: 1 }), + maxResponseSize: schema.oneOf([schema.literal(false), schema.byteSize()], { + defaultValue: false, + }), idleSocketTimeout: schema.duration({ defaultValue: '60s' }), compression: schema.boolean({ defaultValue: false }), username: schema.maybe( @@ -332,6 +335,12 @@ export class ElasticsearchConfig implements IElasticsearchConfig { */ public readonly maxIdleSockets: number; + /** + * The maximum allowed response size (both compressed and uncompressed). + * When defined, responses with a size higher than the set limit will be aborted with an error. + */ + public readonly maxResponseSize?: ByteSizeValue; + /** * The timeout for idle sockets kept open between Kibana and Elasticsearch. If the socket is idle for longer than this timeout, it will be closed. */ @@ -455,6 +464,8 @@ export class ElasticsearchConfig implements IElasticsearchConfig { this.customHeaders = rawConfig.customHeaders; this.maxSockets = rawConfig.maxSockets; this.maxIdleSockets = rawConfig.maxIdleSockets; + this.maxResponseSize = + rawConfig.maxResponseSize !== false ? rawConfig.maxResponseSize : undefined; this.idleSocketTimeout = rawConfig.idleSocketTimeout; this.compression = rawConfig.compression; this.skipStartupConnectionCheck = rawConfig.skipStartupConnectionCheck; diff --git a/packages/core/elasticsearch/core-elasticsearch-server/src/client/client_config.ts b/packages/core/elasticsearch/core-elasticsearch-server/src/client/client_config.ts index 6ef638525c580..e7d119a90622d 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server/src/client/client_config.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server/src/client/client_config.ts @@ -7,6 +7,7 @@ */ import type { Duration } from 'moment'; +import type { ByteSizeValue } from '@kbn/config-schema'; /** * Definition of an API that should redact the requested body in the logs @@ -35,6 +36,7 @@ export interface ElasticsearchClientConfig { requestHeadersWhitelist: string[]; maxSockets: number; maxIdleSockets: number; + maxResponseSize?: ByteSizeValue; idleSocketTimeout: Duration; compression: boolean; sniffOnStart: boolean; diff --git a/packages/core/elasticsearch/core-elasticsearch-server/tsconfig.json b/packages/core/elasticsearch/core-elasticsearch-server/tsconfig.json index 88e18c12e41e0..c3320c12cff9b 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server/tsconfig.json +++ b/packages/core/elasticsearch/core-elasticsearch-server/tsconfig.json @@ -13,7 +13,8 @@ "kbn_references": [ "@kbn/utility-types", "@kbn/es-errors", - "@kbn/core-http-server" + "@kbn/core-http-server", + "@kbn/config-schema" ], "exclude": [ "target/**/*", diff --git a/packages/kbn-es-errors/index.ts b/packages/kbn-es-errors/index.ts index 0d5b6007e5cc8..b5e18f6206474 100644 --- a/packages/kbn-es-errors/index.ts +++ b/packages/kbn-es-errors/index.ts @@ -7,5 +7,10 @@ */ export type { ElasticsearchErrorDetails } from './src/types'; -export { isUnauthorizedError, isResponseError } from './src/errors'; +export { + isUnauthorizedError, + isResponseError, + isRequestAbortedError, + isMaximumResponseSizeExceededError, +} from './src/errors'; export type { UnauthorizedError } from './src/errors'; diff --git a/packages/kbn-es-errors/src/errors.test.ts b/packages/kbn-es-errors/src/errors.test.ts index 59c4296d2bbb2..6a6384585f5a9 100644 --- a/packages/kbn-es-errors/src/errors.test.ts +++ b/packages/kbn-es-errors/src/errors.test.ts @@ -8,7 +8,12 @@ import { errors } from '@elastic/elasticsearch'; import type { TransportResult } from '@elastic/elasticsearch'; -import { isResponseError, isUnauthorizedError } from './errors'; +import { + isResponseError, + isUnauthorizedError, + isRequestAbortedError, + isMaximumResponseSizeExceededError, +} from './errors'; const createApiResponseError = ({ statusCode = 200, @@ -69,3 +74,36 @@ describe('isUnauthorizedError', () => { expect(isUnauthorizedError(new errors.ConfigurationError('foo'))).toBe(false); }); }); + +describe('isRequestAbortedError', () => { + it('returns `true` when the input is a `RequestAbortedError`', () => { + expect(isRequestAbortedError(new errors.RequestAbortedError('Oh no'))).toBe(true); + }); + it('returns `false` when the input is not a `RequestAbortedError`', () => { + expect( + isRequestAbortedError(new errors.ResponseError(createApiResponseError({ statusCode: 500 }))) + ).toBe(false); + }); +}); + +describe('isMaximumResponseSizeExceededError', () => { + it('returns `true` when the input is a `RequestAbortedError` with the right message', () => { + expect( + isMaximumResponseSizeExceededError( + new errors.RequestAbortedError( + `The content length (9000) is bigger than the maximum allowed buffer (42)` + ) + ) + ).toBe(true); + }); + it('returns `false` when the input is a `RequestAbortedError` without the right message', () => { + expect(isMaximumResponseSizeExceededError(new errors.RequestAbortedError('Oh no'))).toBe(false); + }); + it('returns `false` when the input is not a `RequestAbortedError`', () => { + expect( + isMaximumResponseSizeExceededError( + new errors.ResponseError(createApiResponseError({ statusCode: 500 })) + ) + ).toBe(false); + }); +}); diff --git a/packages/kbn-es-errors/src/errors.ts b/packages/kbn-es-errors/src/errors.ts index d46097eb95a2b..24e314f084b59 100644 --- a/packages/kbn-es-errors/src/errors.ts +++ b/packages/kbn-es-errors/src/errors.ts @@ -31,3 +31,17 @@ export function isResponseError(error: unknown): error is errors.ResponseError { export function isUnauthorizedError(error: unknown): error is UnauthorizedError { return isResponseError(error) && error.statusCode === 401; } + +/** + * Checks if the provided `error` is an {@link errors.RequestAbortedError | elasticsearch request aborted error} + * @public + */ +export function isRequestAbortedError(error: unknown): error is errors.RequestAbortedError { + return error instanceof errors.RequestAbortedError; +} + +export function isMaximumResponseSizeExceededError( + error: unknown +): error is errors.RequestAbortedError { + return isRequestAbortedError(error) && error.message.includes('content length'); +} diff --git a/src/core/server/integration_tests/elasticsearch/max_response_size_logging.test.ts b/src/core/server/integration_tests/elasticsearch/max_response_size_logging.test.ts new file mode 100644 index 0000000000000..d9d6cda70c74c --- /dev/null +++ b/src/core/server/integration_tests/elasticsearch/max_response_size_logging.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + createTestServers, + type TestElasticsearchUtils, + type TestKibanaUtils, +} from '@kbn/core-test-helpers-kbn-server'; +import { unsafeConsole } from '@kbn/security-hardening'; + +describe('Elasticsearch max response size', () => { + let mockConsoleLog: jest.SpyInstance; + let esServer: TestElasticsearchUtils; + let kibanaServer: TestKibanaUtils; + + beforeAll(async () => { + mockConsoleLog = jest.spyOn(unsafeConsole, 'log'); + + const { startES, startKibana } = createTestServers({ + adjustTimeout: jest.setTimeout, + settings: { + kbn: { + logging: { + appenders: { + 'test-appender': { + type: 'console', + layout: { + type: 'pattern', + }, + }, + }, + loggers: [ + { name: 'elasticsearch.warnings', appenders: ['test-appender'], level: 'info' }, + ], + }, + }, + }, + }); + + esServer = await startES(); + kibanaServer = await startKibana(); + }); + + beforeEach(() => { + mockConsoleLog.mockClear(); + }); + + afterAll(async () => { + mockConsoleLog.mockRestore(); + await kibanaServer.stop(); + await esServer.stop(); + }); + + it('rejects the response when the response size is larger than the requested limit', async () => { + const esClient = kibanaServer.coreStart.elasticsearch.client.asInternalUser; + + try { + await esClient.cluster.stats({}, { maxResponseSize: 200 }); + expect('should have thrown').toEqual('but it did not'); + } catch (e) { + expect(e.name).toEqual('RequestAbortedError'); + expect(e.message).toContain('is bigger than the maximum allowed string (200)'); + } + }); + + it('logs a warning with the expected message', async () => { + const esClient = kibanaServer.coreStart.elasticsearch.client.asInternalUser; + + try { + await esClient.cluster.stats({}, { maxResponseSize: 200 }); + expect('should have thrown').toEqual('but it did not'); + } catch (e) { + const calls = mockConsoleLog.mock.calls; + + const warningCall = calls + .map((call) => call[0]) + .find((call) => call.includes('elasticsearch.warnings')); + expect(warningCall).toContain( + 'Request against GET /_cluster/stats was aborted: The content length' + ); + expect(warningCall).toContain('is bigger than the maximum allowed string (200)'); + } + }); +}); diff --git a/x-pack/plugins/monitoring/server/config.test.ts b/x-pack/plugins/monitoring/server/config.test.ts index ddaabf7bef2c7..bde75fe4138ee 100644 --- a/x-pack/plugins/monitoring/server/config.test.ts +++ b/x-pack/plugins/monitoring/server/config.test.ts @@ -69,6 +69,7 @@ describe('config schema', () => { "logFetchCount": 10, "logQueries": false, "maxIdleSockets": 256, + "maxResponseSize": false, "maxSockets": 800, "pingTimeout": "PT30S", "requestHeadersWhitelist": Array [ From 771c9545201a3a87163fb0a7c1f58357b206780c Mon Sep 17 00:00:00 2001 From: elena-shostak <165678770+elena-shostak@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:24:35 +0200 Subject: [PATCH 101/127] [Feature Controls] Added a filter_path to the /_xpack/usage ES call (#186370) ## Summary Calls to `/_xpack/usage` in Elasticsearch do not perform well on large clusters. See https://github.com/elastic/elasticsearch/issues/100230. Some users have reported timeouts on this request path. Added a filter_path to the `/_xpack/usage` ES call to optimize the call. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) __Fixes: https://github.com/elastic/kibana/issues/169449__ Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/routes/feature_check/feature_check.test.ts | 9 +++++++++ .../server/routes/feature_check/feature_check.ts | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts b/x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts index 953f65afa9a7c..a1745ec0930b4 100644 --- a/x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts +++ b/x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts @@ -86,6 +86,15 @@ describe('GET role mappings feature check', () => { expect(response.payload).toEqual(asserts.result); expect(mockLicensingContext.license.check).toHaveBeenCalledWith('security', 'basic'); + + if (canReadSecurity) { + expect( + mockCoreContext.elasticsearch.client.asInternalUser.transport.request + ).toHaveBeenCalledWith({ + method: 'GET', + path: '/_xpack/usage?filter_path=remote_clusters.*,security.realms.*', + }); + } }); }; diff --git a/x-pack/plugins/security/server/routes/feature_check/feature_check.ts b/x-pack/plugins/security/server/routes/feature_check/feature_check.ts index 442f040398962..46276957b6c83 100644 --- a/x-pack/plugins/security/server/routes/feature_check/feature_check.ts +++ b/x-pack/plugins/security/server/routes/feature_check/feature_check.ts @@ -88,7 +88,10 @@ async function getEnabledSecurityFeatures(esClient: ElasticsearchClient, logger: // `transport.request` is potentially unsafe when combined with untrusted user input. // Do not augment with such input. const xpackUsagePromise = esClient.transport - .request({ method: 'GET', path: '/_xpack/usage' }) + .request({ + method: 'GET', + path: '/_xpack/usage?filter_path=remote_clusters.*,security.realms.*', + }) .then((body) => body as XPackUsageResponse) .catch((error) => { // fall back to no external realms configured. From a7ffdf87c13cf3c99e973805e612fc6fa25e1689 Mon Sep 17 00:00:00 2001 From: Tre Date: Wed, 19 Jun 2024 10:35:15 +0100 Subject: [PATCH 102/127] [fix on mki] dismiss all toasts before deleting (#186406) ## Summary See details: https://github.com/elastic/kibana/issues/186403 Fixes: https://github.com/elastic/kibana/issues/186403 --- x-pack/test/functional/services/cases/list.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/test/functional/services/cases/list.ts b/x-pack/test/functional/services/cases/list.ts index b449b6f18438a..34db5e7345b3c 100644 --- a/x-pack/test/functional/services/cases/list.ts +++ b/x-pack/test/functional/services/cases/list.ts @@ -24,6 +24,7 @@ export function CasesTableServiceProvider( const browser = getService('browser'); const retry = getService('retry'); const config = getService('config'); + const toasts = getService('toasts'); const assertCaseExists = (index: number, totalCases: number) => { if (index > totalCases - 1) { @@ -49,6 +50,7 @@ export function CasesTableServiceProvider( }, async deleteCase(index: number = 0) { + await toasts.dismissAll(); this.openRowActions(index); await testSubjects.existOrFail('cases-bulk-action-delete'); await testSubjects.click('cases-bulk-action-delete'); From 8a7de8c113f7e45a5f92ea111901a7b0af15c520 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:39:08 +0100 Subject: [PATCH 103/127] [Security Solution][Detection Engine] unskips FTR user roles tests (#186276) ## Summary - addresses https://github.com/elastic/kibana/issues/174028 - checked locally with the [latest main(8.15 snapshot)](https://buildkite.com/elastic/kibana-elasticsearch-snapshot-verify/builds/4126) --- .../user_roles/trial_license_complete_tier/read_privileges.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles/trial_license_complete_tier/read_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles/trial_license_complete_tier/read_privileges.ts index 7727958243823..51a7a9ab1330f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles/trial_license_complete_tier/read_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/user_roles/trial_license_complete_tier/read_privileges.ts @@ -19,8 +19,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - // Failing ES Promotion: https://github.com/elastic/kibana/issues/174028 - describe.skip('@ess @serverless @skipInServerless read_privileges', () => { + describe('@ess @serverless @skipInServerless read_privileges', () => { it('should return expected privileges for elastic admin', async () => { const { body } = await supertest.get(DETECTION_ENGINE_PRIVILEGES_URL).send().expect(200); expect(body).to.eql({ From ca083d27355b82495965003727242a1afcdafd5d Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Wed, 19 Jun 2024 11:48:48 +0200 Subject: [PATCH 104/127] [Dataset quality] Prevent an extra call to ES for degraded docs (#185975) The PR prevents an extra call to ES, thus improving the response time the endpoint `/internal/dataset_quality/data_streams/degraded_docs` takes. **Before** prevent-extra-call-before **After** ![prevent-extra-call-after](https://github.com/elastic/kibana/assets/2748376/312b2600-f5a5-4865-8ba4-9a54f0f52317) --- .../routes/data_streams/get_degraded_docs.ts | 17 +- .../tests/data_streams/degraded_docs.spec.ts | 174 +++++++++++++++++- 2 files changed, 181 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_degraded_docs.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_degraded_docs.ts index bba1f1dce3ec5..fa876d047abd7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_degraded_docs.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_degraded_docs.ts @@ -23,6 +23,8 @@ interface ResultBucket { count: number; } +const SIZE_LIMIT = 10000; + export async function getDegradedDocsPaginated(options: { esClient: ElasticsearchClient; type?: DataStreamType; @@ -65,7 +67,7 @@ export async function getDegradedDocsPaginated(options: { datasets: { composite: { ...(afterKey ? { after: afterKey } : {}), - size: 10000, + size: SIZE_LIMIT, sources: [ { dataset: { terms: { field: 'data_stream.dataset' } } }, { namespace: { terms: { field: 'data_stream.namespace' } } }, @@ -99,9 +101,10 @@ export async function getDegradedDocsPaginated(options: { aggs: aggs(after?.docsCount), }, ]); + const [degradedDocsResponse, totalDocsResponse] = response.responses; const currDegradedDocs = - response.responses[0].aggregations?.datasets.buckets.map((bucket) => ({ + degradedDocsResponse.aggregations?.datasets.buckets.map((bucket) => ({ dataset: `${type}-${bucket.key.dataset}-${bucket.key.namespace}`, count: bucket.doc_count, })) ?? []; @@ -109,7 +112,7 @@ export async function getDegradedDocsPaginated(options: { const degradedDocs = [...prevResults.degradedDocs, ...currDegradedDocs]; const currTotalDocs = - response.responses[1].aggregations?.datasets.buckets.map((bucket) => ({ + totalDocsResponse.aggregations?.datasets.buckets.map((bucket) => ({ dataset: `${type}-${bucket.key.dataset}-${bucket.key.namespace}`, count: bucket.doc_count, })) ?? []; @@ -117,8 +120,8 @@ export async function getDegradedDocsPaginated(options: { const docsCount = [...prevResults.docsCount, ...currTotalDocs]; if ( - response.responses[0].aggregations?.datasets.after_key || - response.responses[1].aggregations?.datasets.after_key + totalDocsResponse.aggregations?.datasets.after_key && + totalDocsResponse.aggregations?.datasets.buckets.length === SIZE_LIMIT ) { return getDegradedDocsPaginated({ esClient, @@ -128,12 +131,12 @@ export async function getDegradedDocsPaginated(options: { datasetQuery, after: { degradedDocs: - (response.responses[0].aggregations?.datasets.after_key as { + (degradedDocsResponse.aggregations?.datasets.after_key as { dataset: string; namespace: string; }) || after?.degradedDocs, docsCount: - (response.responses[1].aggregations?.datasets.after_key as { + (totalDocsResponse.aggregations?.datasets.after_key as { dataset: string; namespace: string; }) || after?.docsCount, diff --git a/x-pack/test/dataset_quality_api_integration/tests/data_streams/degraded_docs.spec.ts b/x-pack/test/dataset_quality_api_integration/tests/data_streams/degraded_docs.spec.ts index 0a8a993ecc416..149f07a98a2f3 100644 --- a/x-pack/test/dataset_quality_api_integration/tests/data_streams/degraded_docs.spec.ts +++ b/x-pack/test/dataset_quality_api_integration/tests/data_streams/degraded_docs.spec.ts @@ -65,9 +65,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .message('This is a log message') .timestamp(timestamp) .dataset('synth.2') - .logLevel( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?' - ) + .logLevel(MORE_THAN_1024_CHARS) .defaults({ 'log.file.path': '/my-service.log', }) @@ -112,5 +110,175 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(stats.body.degradedDocs.length).to.be(0); }); }); + + describe('when there are data streams of different spaces', () => { + const spaces = ['default', 'space1', 'space2']; + const datasetsWithNoDegradedDocs = ['nginx.access', 'apache.access', 'mysql.access']; + const datasetsWithDegradedDocs = ['nginx.error', 'apache.error', 'mysql.error']; + + before(async () => { + for (const space of spaces) { + for (const dataset of datasetsWithNoDegradedDocs) { + await synthtrace.index([ + timerange(start, end) + .interval('1m') + .rate(1) + .generator((timestamp) => + log + .create() + .message('This is a log message') + .timestamp(timestamp) + .dataset(dataset) + .namespace(space) + ), + ]); + } + + for (const dataset of datasetsWithDegradedDocs) { + await synthtrace.index([ + timerange(start, end) + .interval('1m') + .rate(2) + .generator((timestamp: number, index: number) => + log + .create() + .message('This is a log message') + .timestamp(timestamp) + .dataset(dataset) + .namespace(space) + .logLevel(index % 2 === 0 ? MORE_THAN_1024_CHARS : 'This is a log message') + ), + ]); + } + } + }); + + it('returns counts and list of datasets correctly', async () => { + const stats = await callApiAs('datasetQualityLogsUser'); + expect(stats.body.degradedDocs.length).to.be(18); + + const expected = { + degradedDocs: [ + { + dataset: 'logs-apache.access-default', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-apache.access-space1', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-apache.access-space2', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-apache.error-default', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-apache.error-space1', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-apache.error-space2', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-mysql.access-default', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-mysql.access-space1', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-mysql.access-space2', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-mysql.error-default', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-mysql.error-space1', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-mysql.error-space2', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-nginx.access-default', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-nginx.access-space1', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-nginx.access-space2', + count: 0, + docsCount: 1, + percentage: 0, + }, + { + dataset: 'logs-nginx.error-default', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-nginx.error-space1', + count: 1, + docsCount: 2, + percentage: 50, + }, + { + dataset: 'logs-nginx.error-space2', + count: 1, + docsCount: 2, + percentage: 50, + }, + ], + }; + + expect(stats.body).to.eql(expected); + }); + + after(async () => { + await synthtrace.clean(); + }); + }); }); } + +const MORE_THAN_1024_CHARS = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?'; From 384ced6b34558d90c10c258517a94ffaaff64b51 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:51:35 +0200 Subject: [PATCH 105/127] skip failing test suite (#186440) --- .../pages/cis_integrations/cspm/cis_integration_gcp.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts index b75c4aeb2b7f3..121bf7cc2e574 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integrations/cspm/cis_integration_gcp.ts @@ -24,7 +24,8 @@ export default function (providerContext: FtrProviderContext) { const { getPageObjects } = providerContext; const pageObjects = getPageObjects(['cloudPostureDashboard', 'cisAddIntegration', 'header']); - describe('Test adding Cloud Security Posture Integrations CSPM GCP', function () { + // Failing: See https://github.com/elastic/kibana/issues/186440 + describe.skip('Test adding Cloud Security Posture Integrations CSPM GCP', function () { this.tags(['cloud_security_posture_cis_integration_cspm_gcp']); let cisIntegrationGcp: typeof pageObjects.cisAddIntegration.cisGcp; let cisIntegration: typeof pageObjects.cisAddIntegration; From e2b772aeaece0751aa85256a40be8d4c85128b51 Mon Sep 17 00:00:00 2001 From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:35:24 +0100 Subject: [PATCH 106/127] [Rollups] Add deprecation warning callout (#186174) ## Summary This PR adds a deprecation warning callout to the Rollup list view and in the creation form.

Screenshots Screenshot 2024-06-13 at 12 16 03 Screenshot 2024-06-13 at 12 16 10
**How to test:** 1. Start Es and Kibana 2. Add the sample data "Sample web logs"
3. Elasticsearch only allows creating a rollup job if there is an existing rollup usage in the cluster. To simulate rollup usage, create a mock rollup index through Console: ``` PUT /mock_rollup_index { "mappings": { "_meta": { "_rollup": { "id": "logs_job", "index_pattern": "kibana_sample_data_logs", "rollup_index": "rollup_logstash", "cron": "* * * * * ?", "page_size": 1000, "groups": { "date_histogram": { "interval": "60m", "delay": "7d", "time_zone": "UTC", "field": "@timestamp" }, "terms": { "fields": [ "geo.src", "machine.os.keyword" ] }, "histogram": { "interval": "1003", "fields": [ "bytes", "memory" ] } }, "metrics": [ { "field": "bytes", "metrics": [ "avg" ] } ] } } } } ```
4. Create a sample rollup job through Console: ``` PUT _rollup/job/logs_job { "id": "logs_job", "index_pattern": "kibana_sample_data_logs", "rollup_index": "rollup_logstash", "cron": "* * * * * ?", "page_size": 1000, "groups": { "date_histogram": { "interval": "60m", "delay": "7d", "time_zone": "UTC", "field": "@timestamp" }, "terms": { "fields": [ "geo.src", "machine.os.keyword" ] }, "histogram": { "interval": "1003", "fields": [ "bytes", "memory" ] } }, "metrics": [ { "field": "bytes", "metrics": [ "avg" ] } ] } ```
5. Navigate to Stack Management -> Rollup Jobs 6. In the list view, verify that there is deprecation callout with the correct links (to the migration guide and the downsampling doc). 7. Start creating a new rollup job through the UI and verify that the deprecation callout exists on every step. ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + .../deprecation_callout.tsx | 50 +++++++++++++++++++ .../components/deprecation_callout/index.ts | 8 +++ .../crud_app/sections/components/index.js | 2 + .../sections/job_create/job_create.js | 5 ++ .../crud_app/sections/job_list/job_list.js | 5 ++ .../job_create_date_histogram.test.js | 4 ++ .../job_create_histogram.test.js | 4 ++ .../job_create_logistics.test.js | 4 ++ .../job_create_metrics.test.js | 4 ++ .../job_create_review.test.js | 4 ++ .../job_create_terms.test.js | 4 ++ .../test/client_integration/job_list.test.js | 4 ++ 13 files changed, 99 insertions(+) create mode 100644 x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/deprecation_callout.tsx create mode 100644 x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/index.ts diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 3fcd6df837c29..11e29fd14a35f 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -435,6 +435,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D remoteClustersOnPremSetupTrustWithCert: `${ELASTICSEARCH_DOCS}remote-clusters-cert.html`, remoteClustersOnPremSetupTrustWithApiKey: `${ELASTICSEARCH_DOCS}remote-clusters-api-key.html`, remoteClustersCloudSetupTrust: `${ELASTIC_WEBSITE_URL}guide/en/cloud/current/ec-enable-ccs.html`, + rollupMigratingToDownsampling: `${ELASTICSEARCH_DOCS}rollup-migrating-to-downsampling.html`, rrf: `${ELASTICSEARCH_DOCS}rrf.html`, scriptParameters: `${ELASTICSEARCH_DOCS}modules-scripting-using.html#prefer-params`, secureCluster: `${ELASTICSEARCH_DOCS}secure-cluster.html`, diff --git a/x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/deprecation_callout.tsx b/x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/deprecation_callout.tsx new file mode 100644 index 0000000000000..4b36b9a086b69 --- /dev/null +++ b/x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/deprecation_callout.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiCallOut, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { documentationLinks } from '../../../services/documentation_links'; + +/* +A component for displaying a deprecation warning. + */ +export const DeprecationCallout = () => { + return ( + + + {i18n.translate('xpack.rollupJobs.deprecationCallout.migrationGuideLink', { + defaultMessage: 'migration guide', + })} + + ), + downsamplingLink: ( + + {i18n.translate('xpack.rollupJobs.deprecationCallout.downsamplingLink', { + defaultMessage: 'downsampling', + })} + + ), + }} + /> + + ); +}; diff --git a/x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/index.ts b/x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/index.ts new file mode 100644 index 0000000000000..cfa1379a95030 --- /dev/null +++ b/x-pack/plugins/rollup/public/crud_app/sections/components/deprecation_callout/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { DeprecationCallout } from './deprecation_callout'; diff --git a/x-pack/plugins/rollup/public/crud_app/sections/components/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/index.js index ca2dbcfe23f9d..9b1576902b797 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/components/index.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/components/index.js @@ -21,3 +21,5 @@ export { } from './job_details'; export { JobStatus } from './job_status'; + +export { DeprecationCallout } from './deprecation_callout'; diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js index c782e8646b714..4983fbb10ae8f 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js @@ -13,6 +13,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { withKibana } from '@kbn/kibana-react-plugin/public'; +import { DeprecationCallout } from '../components'; import { EuiCallOut, @@ -556,6 +557,10 @@ export class JobCreateUi extends Component { + + + + {saveErrorFeedback} diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js index 04e88cd5848d2..7e03ade8b0221 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js @@ -26,6 +26,7 @@ import { documentationLinks } from '../../services/documentation_links'; import { JobTable } from './job_table'; import { DetailPanel } from './detail_panel'; +import { DeprecationCallout } from '../components'; import { DeprecatedPrompt } from './deprecated_prompt'; const REFRESH_RATE_MS = 30000; @@ -172,6 +173,10 @@ export class JobListUi extends Component { + + + + diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js index 022575e686679..8804f53e65ac6 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js @@ -63,6 +63,10 @@ describe('Create Rollup Job, step 2: Date histogram', () => { expect(exists('rollupJobCreateDateHistogramDocsButton')).toBe(true); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + it('should have the "next" and "back" button visible', () => { expect(exists('rollupJobBackButton')).toBe(true); expect(exists('rollupJobNextButton')).toBe(true); diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js index bf2b76f75b9ab..2ed942604842d 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js @@ -70,6 +70,10 @@ describe('Create Rollup Job, step 4: Histogram', () => { expect(exists('rollupJobCreateHistogramDocsButton')).toBe(true); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + it('should have the "next" and "back" button visible', () => { expect(exists('rollupJobBackButton')).toBe(true); expect(exists('rollupJobNextButton')).toBe(true); diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js index fdeccde8690a7..b073dc97b574a 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js @@ -58,6 +58,10 @@ describe('Create Rollup Job, step 1: Logistics', () => { expect(exists('rollupJobCreateLogisticsDocsButton')).toBe(true); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + it('should only have the "next" button visible', () => { expect(exists('rollupJobBackButton')).toBe(false); expect(exists('rollupJobNextButton')).toBe(true); diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js index 872e26727ba25..b63935b18240c 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js @@ -71,6 +71,10 @@ describe('Create Rollup Job, step 5: Metrics', () => { expect(exists('rollupJobCreateMetricsDocsButton')).toBe(true); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + it('should have the "next" and "back" button visible', () => { expect(exists('rollupJobBackButton')).toBe(true); expect(exists('rollupJobNextButton')).toBe(true); diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js index 5c0ceb7c25f74..d1b42bfaafbcd 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js @@ -70,6 +70,10 @@ describe('Create Rollup Job, step 6: Review', () => { expect(exists('rollupJobCreateReviewTitle')).toBe(true); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + it('should have the "next" and "save" button visible', () => { expect(exists('rollupJobBackButton')).toBe(true); expect(exists('rollupJobNextButton')).toBe(false); diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js index 6736f82279c44..7b55e39ca08f9 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js @@ -68,6 +68,10 @@ describe('Create Rollup Job, step 3: Terms', () => { expect(exists('rollupJobCreateTermsDocsButton')).toBe(true); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + it('should have the "next" and "back" button visible', () => { expect(exists('rollupJobBackButton')).toBe(true); expect(exists('rollupJobNextButton')).toBe(true); diff --git a/x-pack/plugins/rollup/public/test/client_integration/job_list.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_list.test.js index 553fc0712d6fc..b329fce20c7bd 100644 --- a/x-pack/plugins/rollup/public/test/client_integration/job_list.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_list.test.js @@ -62,6 +62,10 @@ describe('', () => { startMock.http.get.mockClear(); }); + test('should have a deprecation callout', () => { + expect(exists('rollupDeprecationCallout')).toBe(true); + }); + test('should open the detail panel when clicking on a job in the table', () => { const { rows } = table.getMetaData('rollupJobsListTable'); const button = rows[0].columns[1].reactWrapper.find('button'); From 74c4d3a85ef1ef1edf22d15e6925ae1c88e2da6e Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Wed, 19 Jun 2024 05:47:18 -0500 Subject: [PATCH 107/127] [Search] Homepage Plugin setup (#186224) ## Summary Introducing the `search_homepage` plugin along with integration into `enterprise_search` and `serverless_search` behind a feature flag. This will allow implementing the feature gated behind the feature flag. To test these changes you can enable the feature flag with the Kibana Dev Console using the following command: ``` POST kbn:/internal/kibana/settings/searchHomepage:homepageEnabled {"value": true} ``` You can then disable the feature flag with the following command: ``` DELETE kbn:/internal/kibana/settings/searchHomepage:homepageEnabled ``` ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + config/serverless.es.yml | 3 + docs/developer/plugin-list.asciidoc | 4 + package.json | 1 + packages/deeplinks/search/constants.ts | 1 + packages/deeplinks/search/deep_links.ts | 3 + packages/kbn-optimizer/limits.yml | 1 + .../test_suites/core_plugins/rendering.ts | 3 +- tsconfig.base.json | 2 + x-pack/.i18nrc.json | 1 + x-pack/plugins/enterprise_search/kibana.jsonc | 1 + .../__mocks__/kea_logic/kibana_logic.mock.ts | 2 + .../public/applications/index.tsx | 2 + .../components/layout/page_template.test.tsx | 28 +++++ .../components/layout/page_template.tsx | 37 ++++++ .../components/search_homepage.tsx | 35 ++++++ .../applications/search_homepage/index.tsx | 42 +++++++ .../search_homepage/jest.config.js | 26 +++++ .../shared/kibana/kibana_logic.ts | 7 ++ .../shared/kibana_chrome/breadcrumbs_home.ts | 18 +++ .../kibana_chrome/generate_breadcrumbs.ts | 7 +- .../public/applications/shared/layout/nav.tsx | 8 +- .../test_helpers/test_utils.test_helper.tsx | 6 +- .../public/navigation_tree.ts | 6 +- .../enterprise_search/public/plugin.ts | 107 +++++++++++++----- .../plugins/enterprise_search/tsconfig.json | 3 +- x-pack/plugins/search_homepage/README.mdx | 3 + .../plugins/search_homepage/common/index.ts | 14 +++ x-pack/plugins/search_homepage/jest.config.js | 15 +++ x-pack/plugins/search_homepage/kibana.jsonc | 26 +++++ .../search_homepage/public/application.tsx | 37 ++++++ .../public/components/search_homepage.tsx | 32 ++++++ .../components/search_homepage_body.tsx | 24 ++++ .../components/search_homepage_header.tsx | 26 +++++ .../public/components/stack_app.tsx | 19 ++++ .../search_homepage/public/embeddable.tsx | 12 ++ .../search_homepage/public/feature_flags.ts | 13 +++ .../public/hooks/use_kibana.ts | 11 ++ .../plugins/search_homepage/public/index.ts | 20 ++++ .../plugins/search_homepage/public/plugin.ts | 80 +++++++++++++ .../plugins/search_homepage/public/router.tsx | 19 ++++ .../plugins/search_homepage/public/types.ts | 74 ++++++++++++ .../plugins/search_homepage/server/config.ts | 27 +++++ .../plugins/search_homepage/server/index.ts | 17 +++ .../plugins/search_homepage/server/plugin.ts | 28 +++++ .../plugins/search_homepage/server/types.ts | 11 ++ x-pack/plugins/search_homepage/tsconfig.json | 30 +++++ x-pack/plugins/serverless_search/kibana.jsonc | 1 + .../public/navigation_tree.ts | 6 +- .../serverless_search/public/plugin.ts | 31 ++++- .../plugins/serverless_search/public/types.ts | 24 ++-- .../plugins/serverless_search/tsconfig.json | 1 + .../functional/page_objects/index.ts | 2 + .../page_objects/svl_search_homepage.ts | 26 +++++ .../functional/services/index.ts | 2 + .../functional/services/ui_settings.ts | 32 ++++++ .../functional/test_suites/search/index.ts | 1 + .../test_suites/search/search_homepage.ts | 58 ++++++++++ yarn.lock | 4 + 59 files changed, 1025 insertions(+), 56 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/search_homepage/components/search_homepage.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/search_homepage/index.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/search_homepage/jest.config.js create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/breadcrumbs_home.ts create mode 100644 x-pack/plugins/search_homepage/README.mdx create mode 100644 x-pack/plugins/search_homepage/common/index.ts create mode 100644 x-pack/plugins/search_homepage/jest.config.js create mode 100644 x-pack/plugins/search_homepage/kibana.jsonc create mode 100644 x-pack/plugins/search_homepage/public/application.tsx create mode 100644 x-pack/plugins/search_homepage/public/components/search_homepage.tsx create mode 100644 x-pack/plugins/search_homepage/public/components/search_homepage_body.tsx create mode 100644 x-pack/plugins/search_homepage/public/components/search_homepage_header.tsx create mode 100644 x-pack/plugins/search_homepage/public/components/stack_app.tsx create mode 100644 x-pack/plugins/search_homepage/public/embeddable.tsx create mode 100644 x-pack/plugins/search_homepage/public/feature_flags.ts create mode 100644 x-pack/plugins/search_homepage/public/hooks/use_kibana.ts create mode 100644 x-pack/plugins/search_homepage/public/index.ts create mode 100644 x-pack/plugins/search_homepage/public/plugin.ts create mode 100644 x-pack/plugins/search_homepage/public/router.tsx create mode 100644 x-pack/plugins/search_homepage/public/types.ts create mode 100644 x-pack/plugins/search_homepage/server/config.ts create mode 100644 x-pack/plugins/search_homepage/server/index.ts create mode 100644 x-pack/plugins/search_homepage/server/plugin.ts create mode 100644 x-pack/plugins/search_homepage/server/types.ts create mode 100644 x-pack/plugins/search_homepage/tsconfig.json create mode 100644 x-pack/test_serverless/functional/page_objects/svl_search_homepage.ts create mode 100644 x-pack/test_serverless/functional/services/ui_settings.ts create mode 100644 x-pack/test_serverless/functional/test_suites/search/search_homepage.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 690698e02a142..e06b53da0ab57 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -716,6 +716,7 @@ packages/kbn-search-connectors @elastic/search-kibana x-pack/plugins/search_connectors @elastic/search-kibana packages/kbn-search-errors @elastic/kibana-data-discovery examples/search_examples @elastic/kibana-data-discovery +x-pack/plugins/search_homepage @elastic/search-kibana packages/kbn-search-index-documents @elastic/search-kibana x-pack/plugins/search_inference_endpoints @elastic/search-kibana x-pack/plugins/search_notebooks @elastic/search-kibana diff --git a/config/serverless.es.yml b/config/serverless.es.yml index 531fa5520c0ae..a170cf569b54d 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -69,3 +69,6 @@ xpack.searchInferenceEndpoints.ui.enabled: false # Search Notebooks xpack.search.notebooks.catalog.url: https://elastic-enterprise-search.s3.us-east-2.amazonaws.com/serverless/catalog.json + +# Search Homepage +xpack.search.homepage.ui.enabled: true diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index f78070b9bfa49..fc15206bd284d 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -789,6 +789,10 @@ It uses Chromium and Puppeteer underneath to run the browser in headless mode. |This plugin contains common assets and endpoints for the use of connectors in Kibana. Primarily used by the enterprise_search and serverless_search plugins. +|{kib-repo}blob/{branch}/x-pack/plugins/search_homepage/README.mdx[searchHomepage] +|The Search Homepage is a shared homepage for elasticsearch users. + + |{kib-repo}blob/{branch}/x-pack/plugins/search_inference_endpoints/README.md[searchInferenceEndpoints] |The Inference Endpoints is a tool used to manage inference endpoints diff --git a/package.json b/package.json index 48abd4ddd30b7..efd020e91df66 100644 --- a/package.json +++ b/package.json @@ -727,6 +727,7 @@ "@kbn/search-connectors-plugin": "link:x-pack/plugins/search_connectors", "@kbn/search-errors": "link:packages/kbn-search-errors", "@kbn/search-examples-plugin": "link:examples/search_examples", + "@kbn/search-homepage": "link:x-pack/plugins/search_homepage", "@kbn/search-index-documents": "link:packages/kbn-search-index-documents", "@kbn/search-inference-endpoints": "link:x-pack/plugins/search_inference_endpoints", "@kbn/search-notebooks": "link:x-pack/plugins/search_notebooks", diff --git a/packages/deeplinks/search/constants.ts b/packages/deeplinks/search/constants.ts index 36d31d22dfe21..3fdcc78bb68a1 100644 --- a/packages/deeplinks/search/constants.ts +++ b/packages/deeplinks/search/constants.ts @@ -17,3 +17,4 @@ export const SERVERLESS_ES_APP_ID = 'serverlessElasticsearch'; export const SERVERLESS_ES_CONNECTORS_ID = 'serverlessConnectors'; export const SERVERLESS_ES_SEARCH_PLAYGROUND_ID = 'searchPlayground'; export const SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID = 'searchInferenceEndpoints'; +export const SEARCH_HOMEPAGE = 'searchHomepage'; diff --git a/packages/deeplinks/search/deep_links.ts b/packages/deeplinks/search/deep_links.ts index 8eeceff8f8ca2..f004d1b2c9dd6 100644 --- a/packages/deeplinks/search/deep_links.ts +++ b/packages/deeplinks/search/deep_links.ts @@ -17,6 +17,7 @@ import { ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID, SERVERLESS_ES_SEARCH_PLAYGROUND_ID, SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID, + SEARCH_HOMEPAGE, } from './constants'; export type EnterpriseSearchApp = typeof ENTERPRISE_SEARCH_APP_ID; @@ -29,6 +30,7 @@ export type ServerlessSearchApp = typeof SERVERLESS_ES_APP_ID; export type ConnectorsId = typeof SERVERLESS_ES_CONNECTORS_ID; export type SearchPlaygroundId = typeof SERVERLESS_ES_SEARCH_PLAYGROUND_ID; export type SearchInferenceEndpointsId = typeof SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID; +export type SearchHomepage = typeof SEARCH_HOMEPAGE; export type ContentLinkId = 'searchIndices' | 'connectors' | 'webCrawlers'; @@ -47,6 +49,7 @@ export type DeepLinkId = | ConnectorsId | SearchPlaygroundId | SearchInferenceEndpointsId + | SearchHomepage | `${EnterpriseSearchContentApp}:${ContentLinkId}` | `${EnterpriseSearchApplicationsApp}:${ApplicationsLinkId}` | `${EnterpriseSearchAppsearchApp}:${AppsearchLinkId}`; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 336cfd2c6b93d..c3ffc507387b8 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -132,6 +132,7 @@ pageLoadAssetSize: screenshotMode: 17856 screenshotting: 22870 searchConnectors: 30000 + searchHomepage: 19831 searchInferenceEndpoints: 20470 searchNotebooks: 18942 searchPlayground: 19325 diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 31e0a44b9e823..19eeef57ba62b 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -313,8 +313,9 @@ export default function ({ getService }: PluginFunctionalProviderContext) { // 'xpack.reporting.poll.jobsRefresh.intervalErrorMultiplier (number)', 'xpack.rollup.ui.enabled (boolean)', 'xpack.saved_object_tagging.cache_refresh_interval (duration)', - 'xpack.searchPlayground.ui.enabled (boolean)', + 'xpack.search.homepage.ui.enabled (boolean)', 'xpack.searchInferenceEndpoints.ui.enabled (boolean)', + 'xpack.searchPlayground.ui.enabled (boolean)', 'xpack.security.loginAssistanceMessage (string)', 'xpack.security.sameSiteCookies (alternatives)', 'xpack.security.showInsecureClusterWarning (boolean)', diff --git a/tsconfig.base.json b/tsconfig.base.json index ea18fe456af85..0f8d9a11563e0 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1426,6 +1426,8 @@ "@kbn/search-errors/*": ["packages/kbn-search-errors/*"], "@kbn/search-examples-plugin": ["examples/search_examples"], "@kbn/search-examples-plugin/*": ["examples/search_examples/*"], + "@kbn/search-homepage": ["x-pack/plugins/search_homepage"], + "@kbn/search-homepage/*": ["x-pack/plugins/search_homepage/*"], "@kbn/search-index-documents": ["packages/kbn-search-index-documents"], "@kbn/search-index-documents/*": ["packages/kbn-search-index-documents/*"], "@kbn/search-inference-endpoints": ["x-pack/plugins/search_inference_endpoints"], diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 2943af3cf46d5..1f224ca164e52 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -92,6 +92,7 @@ "xpack.rollupJobs": ["plugins/rollup"], "xpack.runtimeFields": "plugins/runtime_fields", "xpack.screenshotting": "plugins/screenshotting", + "xpack.searchHomepage": "plugins/search_homepage", "xpack.searchNotebooks": "plugins/search_notebooks", "xpack.searchPlayground": "plugins/search_playground", "xpack.searchInferenceEndpoints": "plugins/search_inference_endpoints", diff --git a/x-pack/plugins/enterprise_search/kibana.jsonc b/x-pack/plugins/enterprise_search/kibana.jsonc index 3855fd3d9e1f9..0dc2562ff2fe3 100644 --- a/x-pack/plugins/enterprise_search/kibana.jsonc +++ b/x-pack/plugins/enterprise_search/kibana.jsonc @@ -30,6 +30,7 @@ "guidedOnboarding", "console", "searchConnectors", + "searchHomepage", "searchPlayground", "searchInferenceEndpoints", "embeddable", diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts index cca5523ded681..5f4774be15b96 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts @@ -45,6 +45,7 @@ export const mockKibanaValues = { history: mockHistory, indexMappingComponent: null, isCloud: false, + isSearchHomepageEnabled: false, isSidebarEnabled: true, lens: { EmbeddableComponent: jest.fn(), @@ -64,6 +65,7 @@ export const mockKibanaValues = { hasWebCrawler: true, }, renderHeaderActions: jest.fn(), + searchHomepage: null, searchInferenceEndpoints: null, searchPlayground: searchPlaygroundMock.createStart(), security: securityMock.createStart(), diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index ea45e121470e2..98d6677c35fc1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -117,6 +117,7 @@ export const renderApp = ( guidedOnboarding, history, indexMappingComponent, + isSearchHomepageEnabled: plugins.searchHomepage?.isHomepageFeatureEnabled() ?? false, isSidebarEnabled, lens, ml, @@ -127,6 +128,7 @@ export const renderApp = ( params.setHeaderActionMenu( HeaderActions ? renderHeaderActions.bind(null, HeaderActions, store, params) : undefined ), + searchHomepage: plugins.searchHomepage, searchPlayground: plugins.searchPlayground, searchInferenceEndpoints: plugins.searchInferenceEndpoints, security, diff --git a/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.test.tsx new file mode 100644 index 0000000000000..c44cc39c5eb1d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.test.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { TestHelper } from '../../../test_helpers/test_utils.test_helper'; + +import { SearchHomepagePageTemplate } from './page_template'; + +describe('SearchHomepagePageTemplate', () => { + beforeAll(() => { + TestHelper.prepare(); + }); + + it('renders as expected', async () => { + const { container } = TestHelper.render( + +
Test
+
+ ); + + expect(container.querySelector('.kbnSolutionNav__title')).toHaveTextContent('Search'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.tsx new file mode 100644 index 0000000000000..76f2e6e526239 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/layout/page_template.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { SEARCH_PRODUCT_NAME } from '../../../../../common/constants'; +import { SetSearchChrome } from '../../../shared/kibana_chrome'; +import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; +import { useEnterpriseSearchNav } from '../../../shared/layout'; +import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry'; + +export const SearchHomepagePageTemplate: React.FC = ({ + children, + pageChrome, + pageViewTelemetry, + ...pageTemplateProps +}) => { + return ( + } + > + {pageViewTelemetry && ( + + )} + {children} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/search_homepage.tsx b/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/search_homepage.tsx new file mode 100644 index 0000000000000..a605010fcb00d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/search_homepage/components/search_homepage.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { KibanaLogic } from '../../shared/kibana'; +import { SetSearchChrome } from '../../shared/kibana_chrome'; + +import { SearchHomepagePageTemplate } from './layout/page_template'; + +export const SearchHomepagePage = () => { + const { isSearchHomepageEnabled, searchHomepage } = useValues(KibanaLogic); + + if (!isSearchHomepageEnabled || !searchHomepage) { + return null; + } + + return ( + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/search_homepage/index.tsx b/x-pack/plugins/enterprise_search/public/applications/search_homepage/index.tsx new file mode 100644 index 0000000000000..43963f21d3b5d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/search_homepage/index.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { Routes, Route } from '@kbn/shared-ux-router'; + +import { isVersionMismatch } from '../../../common/is_version_mismatch'; +import type { InitialAppData } from '../../../common/types'; +import { VersionMismatchPage } from '../shared/version_mismatch'; + +import { SearchHomepagePage } from './components/search_homepage'; + +export const SearchHomepage: React.FC = (props) => { + const { enterpriseSearchVersion, kibanaVersion } = props; + const incompatibleVersions = isVersionMismatch(enterpriseSearchVersion, kibanaVersion); + + const showView = () => { + if (incompatibleVersions) { + return ( + + ); + } + + return ; + }; + + return ( + + + {showView()} + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/search_homepage/jest.config.js b/x-pack/plugins/enterprise_search/public/applications/search_homepage/jest.config.js new file mode 100644 index 0000000000000..c18a3561afb65 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/search_homepage/jest.config.js @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../../..', + roots: ['/x-pack/plugins/enterprise_search/public/applications/search_homepage'], + collectCoverage: true, + coverageReporters: ['text', 'html'], + collectCoverageFrom: [ + '/x-pack/plugins/enterprise_search/public/applications/**/*.{ts,tsx}', + '!/x-pack/plugins/enterprise_search/public/*.ts', + '!/x-pack/plugins/enterprise_search/server/*.ts', + '!/x-pack/plugins/enterprise_search/public/applications/test_helpers/**/*.{ts,tsx}', + ], + coverageDirectory: + '/target/kibana-coverage/jest/x-pack/plugins/enterprise_search/public/applications/search_homepage', + modulePathIgnorePatterns: [ + '/x-pack/plugins/enterprise_search/public/applications/app_search/cypress', + '/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress', + ], +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index da18e9e8bb44f..4920b25cffd75 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -29,6 +29,7 @@ import { LensPublicStart } from '@kbn/lens-plugin/public'; import { MlPluginStart } from '@kbn/ml-plugin/public'; import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants'; import { ConnectorDefinition } from '@kbn/search-connectors-plugin/public'; +import type { SearchHomepagePluginStart } from '@kbn/search-homepage/public'; import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public'; import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public'; import { AuthenticatedUser, SecurityPluginStart } from '@kbn/security-plugin/public'; @@ -58,6 +59,7 @@ export interface KibanaLogicProps { guidedOnboarding?: GuidedOnboardingPluginStart; history: ScopedHistory; indexMappingComponent?: React.FC; + isSearchHomepageEnabled: boolean; isSidebarEnabled: boolean; lens?: LensPublicStart; ml?: MlPluginStart; @@ -65,6 +67,7 @@ export interface KibanaLogicProps { productAccess: ProductAccess; productFeatures: ProductFeatures; renderHeaderActions(HeaderActions?: FC): void; + searchHomepage?: SearchHomepagePluginStart; searchPlayground?: SearchPlaygroundPluginStart; searchInferenceEndpoints?: SearchInferenceEndpointsPluginStart; security?: SecurityPluginStart; @@ -91,6 +94,7 @@ export interface KibanaValues { history: ScopedHistory; indexMappingComponent: React.FC | null; isCloud: boolean; + isSearchHomepageEnabled: boolean; isSidebarEnabled: boolean; lens: LensPublicStart | null; ml: MlPluginStart | null; @@ -98,6 +102,7 @@ export interface KibanaValues { productAccess: ProductAccess; productFeatures: ProductFeatures; renderHeaderActions(HeaderActions?: FC): void; + searchHomepage: SearchHomepagePluginStart | null; searchPlayground: SearchPlaygroundPluginStart | null; searchInferenceEndpoints: SearchInferenceEndpointsPluginStart | null; security: SecurityPluginStart | null; @@ -129,6 +134,7 @@ export const KibanaLogic = kea>({ guidedOnboarding: [props.guidedOnboarding || null, {}], history: [props.history, {}], indexMappingComponent: [props.indexMappingComponent || null, {}], + isSearchHomepageEnabled: [props.isSearchHomepageEnabled, {}], isSidebarEnabled: [props.isSidebarEnabled, {}], lens: [props.lens || null, {}], ml: [props.ml || null, {}], @@ -143,6 +149,7 @@ export const KibanaLogic = kea>({ productAccess: [props.productAccess, {}], productFeatures: [props.productFeatures, {}], renderHeaderActions: [props.renderHeaderActions, {}], + searchHomepage: [props.searchHomepage || null, {}], searchPlayground: [props.searchPlayground || null, {}], searchInferenceEndpoints: [props.searchInferenceEndpoints || null, {}], security: [props.security || null, {}], diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/breadcrumbs_home.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/breadcrumbs_home.ts new file mode 100644 index 0000000000000..34e9e12c88b76 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/breadcrumbs_home.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ENTERPRISE_SEARCH_OVERVIEW_PLUGIN } from '../../../../common/constants'; + +/** + * HACK for base homepage URL, this can be removed and updated to a static + * URL when Search Homepage is no longer feature flagged. + */ +const breadCrumbHome = { url: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL }; +export const getHomeURL = () => breadCrumbHome.url; +export const setBreadcrumbHomeUrl = (url: string) => { + breadCrumbHome.url = url; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts index ac3e6d7a6437d..5798a48680d1f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts @@ -15,7 +15,6 @@ import { APP_SEARCH_PLUGIN, ENTERPRISE_SEARCH_CONTENT_PLUGIN, INFERENCE_ENDPOINTS_PLUGIN, - ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, ENTERPRISE_SEARCH_PRODUCT_NAME, AI_SEARCH_PLUGIN, SEARCH_EXPERIENCES_PLUGIN, @@ -29,6 +28,8 @@ import { HttpLogic } from '../http'; import { KibanaLogic } from '../kibana'; import { letBrowserHandleEvent, createHref } from '../react_router_helpers'; +import { getHomeURL } from './breadcrumbs_home'; + /** * Types */ @@ -107,7 +108,7 @@ export const useSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) => useEuiBreadcrumbs([ { text: SEARCH_PRODUCT_NAME, - path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, + path: getHomeURL(), shouldNotCreateHref: true, }, ...breadcrumbs, @@ -117,7 +118,7 @@ export const useEnterpriseSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) => useEuiBreadcrumbs([ { text: ENTERPRISE_SEARCH_PRODUCT_NAME, - path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, + path: getHomeURL(), shouldNotCreateHref: true, }, ...breadcrumbs, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx index bd53ed235d4cb..77454581c61e7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx @@ -49,7 +49,8 @@ import { generateNavLink } from './nav_link_helpers'; * @returns The Enterprise Search navigation items */ export const useEnterpriseSearchNav = (alwaysReturn = false) => { - const { isSidebarEnabled, productAccess } = useValues(KibanaLogic); + const { isSearchHomepageEnabled, searchHomepage, isSidebarEnabled, productAccess } = + useValues(KibanaLogic); const indicesNavItems = useIndicesNav(); if (!isSidebarEnabled && !alwaysReturn) return undefined; @@ -66,7 +67,10 @@ export const useEnterpriseSearchNav = (alwaysReturn = false) => { ...generateNavLink({ shouldNotCreateHref: true, shouldShowActiveForSubroutes: true, - to: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, + to: + isSearchHomepageEnabled && searchHomepage + ? searchHomepage.app.appRoute + : ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, }), }, { diff --git a/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx b/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx index 5601c006a4433..0050165b8be50 100644 --- a/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx @@ -62,6 +62,7 @@ export const mockKibanaProps: KibanaLogicProps = { indexMappingComponent: () => { return <>; }, + isSearchHomepageEnabled: false, isSidebarEnabled: true, lens: { EmbeddableComponent: jest.fn(), @@ -84,6 +85,7 @@ export const mockKibanaProps: KibanaLogicProps = { hasWebCrawler: true, }, renderHeaderActions: jest.fn(), + searchHomepage: undefined, searchPlayground: searchPlaygroundMock.createStart(), security: securityMock.createStart(), setBreadcrumbs: jest.fn(), @@ -114,7 +116,7 @@ interface TestHelper { defaultMockValues: typeof DEFAULT_VALUES; mountLogic: (logicFile: LogicFile, props?: object) => void; prepare: (options?: PrepareOptions) => void; - render: (children: JSX.Element) => void; + render: (children: JSX.Element) => ReturnType; } export const TestHelper: TestHelper = { @@ -147,7 +149,7 @@ export const TestHelper: TestHelper = { TestHelper.actionsToRun.forEach((action) => { action(); }); - testingLibraryRender( + return testingLibraryRender( {children} diff --git a/x-pack/plugins/enterprise_search/public/navigation_tree.ts b/x-pack/plugins/enterprise_search/public/navigation_tree.ts index dc079aec90688..051cfaa6779af 100644 --- a/x-pack/plugins/enterprise_search/public/navigation_tree.ts +++ b/x-pack/plugins/enterprise_search/public/navigation_tree.ts @@ -67,12 +67,14 @@ const euiItemTypeToNodeDefinition = ({ export const getNavigationTreeDefinition = ({ dynamicItems$, + isSearchHomepageEnabled, }: { dynamicItems$: Observable; + isSearchHomepageEnabled: boolean; }): AddSolutionNavigationArg => { return { dataTestSubj: 'searchSideNav', - homePage: 'enterpriseSearch', + homePage: isSearchHomepageEnabled ? 'searchHomepage' : 'enterpriseSearch', icon, id: 'es', navigationTree$: dynamicItems$.pipe( @@ -84,7 +86,7 @@ export const getNavigationTreeDefinition = ({ breadcrumbStatus: 'hidden', children: [ { - link: 'enterpriseSearch', + link: isSearchHomepageEnabled ? 'searchHomepage' : 'enterpriseSearch', }, { getIsActive: ({ pathNameSerialized, prepend }) => { diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index 9c03fb623fa3d..280de2f04356b 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -32,6 +32,10 @@ import { MlPluginStart } from '@kbn/ml-plugin/public'; import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants'; import { SearchConnectorsPluginStart } from '@kbn/search-connectors-plugin/public'; +import type { + SearchHomepagePluginSetup, + SearchHomepagePluginStart, +} from '@kbn/search-homepage/public'; import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public'; import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public'; import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/public'; @@ -67,6 +71,7 @@ import { import { INFERENCE_ENDPOINTS_PATH } from './applications/enterprise_search_relevance/routes'; import { docLinks } from './applications/shared/doc_links'; +import { setBreadcrumbHomeUrl } from './applications/shared/kibana_chrome/breadcrumbs_home'; import type { DynamicSideNavItems } from './navigation_tree'; export interface ClientData extends InitialAppData { @@ -80,6 +85,7 @@ export type EnterpriseSearchPublicStart = ReturnType { - const kibanaDeps = await this.getKibanaDeps(core, params, cloud); - const { chrome, http } = kibanaDeps.core; - chrome.docTitle.change(ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME); + if (useSearchHomepage) { + const { app } = plugins.searchHomepage!; + core.application.register({ + ...app, + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, + visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'], + mount: async (params: AppMountParameters) => { + const kibanaDeps = await this.getKibanaDeps(core, params, cloud); + const { chrome, http } = kibanaDeps.core; + chrome.docTitle.change(app.title); - await this.getInitialData(http); - const pluginData = this.getPluginData(); + await this.getInitialData(http); + const pluginData = this.getPluginData(); - const { renderApp } = await import('./applications'); - const { EnterpriseSearchOverview } = await import( - './applications/enterprise_search_overview' - ); + const { renderApp } = await import('./applications'); + const { SearchHomepage } = await import('./applications/search_homepage'); - return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData); - }, - title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE, - visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'], - }); + return renderApp(SearchHomepage, kibanaDeps, pluginData); + }, + }); + setBreadcrumbHomeUrl(app.appRoute); + } else { + core.application.register({ + appRoute: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, + id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + mount: async (params: AppMountParameters) => { + const kibanaDeps = await this.getKibanaDeps(core, params, cloud); + const { chrome, http } = kibanaDeps.core; + chrome.docTitle.change(ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME); + + await this.getInitialData(http); + const pluginData = this.getPluginData(); + + const { renderApp } = await import('./applications'); + const { EnterpriseSearchOverview } = await import( + './applications/enterprise_search_overview' + ); + + return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData); + }, + title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE, + visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'], + }); + } core.application.register({ appRoute: ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL, @@ -512,14 +545,27 @@ export class EnterpriseSearchPlugin implements Plugin { } if (plugins.home) { - plugins.home.featureCatalogue.registerSolution({ - description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION, - icon: 'logoEnterpriseSearch', - id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, - order: 100, - path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, - title: SEARCH_PRODUCT_NAME, - }); + if (useSearchHomepage) { + const { searchHomepage } = plugins; + + plugins.home.featureCatalogue.registerSolution({ + description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION, + icon: 'logoEnterpriseSearch', + id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + order: 100, + path: searchHomepage!.app.appRoute, + title: SEARCH_PRODUCT_NAME, + }); + } else { + plugins.home.featureCatalogue.registerSolution({ + description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION, + icon: 'logoEnterpriseSearch', + id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID, + order: 100, + path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, + title: SEARCH_PRODUCT_NAME, + }); + } plugins.home.featureCatalogue.register({ category: 'data', @@ -587,7 +633,10 @@ export class EnterpriseSearchPlugin implements Plugin { import('./navigation_tree').then(({ getNavigationTreeDefinition }) => { return plugins.navigation.addSolutionNavigation( - getNavigationTreeDefinition({ dynamicItems$: this.sideNavDynamicItems$ }) + getNavigationTreeDefinition({ + dynamicItems$: this.sideNavDynamicItems$, + isSearchHomepageEnabled: plugins.searchHomepage?.isHomepageFeatureEnabled() ?? false, + }) ); }); diff --git a/x-pack/plugins/enterprise_search/tsconfig.json b/x-pack/plugins/enterprise_search/tsconfig.json index 3a66b8350be4f..a6bb797de5eb1 100644 --- a/x-pack/plugins/enterprise_search/tsconfig.json +++ b/x-pack/plugins/enterprise_search/tsconfig.json @@ -79,6 +79,7 @@ "@kbn/cloud", "@kbn/try-in-console", "@kbn/core-chrome-browser", - "@kbn/navigation-plugin" + "@kbn/navigation-plugin", + "@kbn/search-homepage" ] } diff --git a/x-pack/plugins/search_homepage/README.mdx b/x-pack/plugins/search_homepage/README.mdx new file mode 100644 index 0000000000000..00ba4f491c607 --- /dev/null +++ b/x-pack/plugins/search_homepage/README.mdx @@ -0,0 +1,3 @@ +# Search Homepage + +The Search Homepage is a shared homepage for elasticsearch users. diff --git a/x-pack/plugins/search_homepage/common/index.ts b/x-pack/plugins/search_homepage/common/index.ts new file mode 100644 index 0000000000000..d93d5c49f8cc5 --- /dev/null +++ b/x-pack/plugins/search_homepage/common/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const PLUGIN_ID = 'searchHomepage'; +export const PLUGIN_NAME = 'searchHomepage'; + +/** + * UI Setting id for the Search Homepage feature flag + */ +export const HOMEPAGE_FEATURE_FLAG_ID = 'searchHomepage:homepageEnabled'; diff --git a/x-pack/plugins/search_homepage/jest.config.js b/x-pack/plugins/search_homepage/jest.config.js new file mode 100644 index 0000000000000..65cd8f1e34252 --- /dev/null +++ b/x-pack/plugins/search_homepage/jest.config.js @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/x-pack/plugins/search_homepage'], + coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/search_homepage', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['/x-pack/plugins/search_homepage/{public,server}/**/*.{ts,tsx}'], +}; diff --git a/x-pack/plugins/search_homepage/kibana.jsonc b/x-pack/plugins/search_homepage/kibana.jsonc new file mode 100644 index 0000000000000..0e345ab0d330a --- /dev/null +++ b/x-pack/plugins/search_homepage/kibana.jsonc @@ -0,0 +1,26 @@ +{ + "type": "plugin", + "id": "@kbn/search-homepage", + "owner": "@elastic/search-kibana", + "plugin": { + "id": "searchHomepage", + "server": true, + "browser": true, + "configPath": [ + "xpack", + "search", + "homepage" + ], + "requiredPlugins": [ + "share", + ], + "optionalPlugins": [ + "cloud", + "console", + "usageCollection", + ], + "requiredBundles": [ + "kibanaReact" + ] + } +} diff --git a/x-pack/plugins/search_homepage/public/application.tsx b/x-pack/plugins/search_homepage/public/application.tsx new file mode 100644 index 0000000000000..4af256de498ed --- /dev/null +++ b/x-pack/plugins/search_homepage/public/application.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { CoreStart } from '@kbn/core/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { I18nProvider } from '@kbn/i18n-react'; +import { Router } from '@kbn/shared-ux-router'; +import { SearchHomepageAppPluginStartDependencies } from './types'; +import { HomepageRouter } from './router'; + +export const renderApp = async ( + core: CoreStart, + services: SearchHomepageAppPluginStartDependencies, + element: HTMLElement +) => { + ReactDOM.render( + + + + + + + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/x-pack/plugins/search_homepage/public/components/search_homepage.tsx b/x-pack/plugins/search_homepage/public/components/search_homepage.tsx new file mode 100644 index 0000000000000..7af02cbcf3275 --- /dev/null +++ b/x-pack/plugins/search_homepage/public/components/search_homepage.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo } from 'react'; +import { EuiPageTemplate } from '@elastic/eui'; + +import { useKibana } from '../hooks/use_kibana'; +import { SearchHomepageBody } from './search_homepage_body'; +import { SearchHomepageHeader } from './search_homepage_header'; + +export const SearchHomepagePage = () => { + const { + services: { console: consolePlugin }, + } = useKibana(); + + const embeddableConsole = useMemo( + () => (consolePlugin?.EmbeddableConsole ? : null), + [consolePlugin] + ); + + return ( + + + + {embeddableConsole} + + ); +}; diff --git a/x-pack/plugins/search_homepage/public/components/search_homepage_body.tsx b/x-pack/plugins/search_homepage/public/components/search_homepage_body.tsx new file mode 100644 index 0000000000000..808393594e7d8 --- /dev/null +++ b/x-pack/plugins/search_homepage/public/components/search_homepage_body.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; + +export const SearchHomepageBody = () => ( + +
+ +); diff --git a/x-pack/plugins/search_homepage/public/components/search_homepage_header.tsx b/x-pack/plugins/search_homepage/public/components/search_homepage_header.tsx new file mode 100644 index 0000000000000..941655d67cdab --- /dev/null +++ b/x-pack/plugins/search_homepage/public/components/search_homepage_header.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { EuiPageTemplate, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; + +export const SearchHomepageHeader = () => ( + +

+ +

+ + } + data-test-subj="search-homepage-header" + rightSideItems={[]} + /> +); diff --git a/x-pack/plugins/search_homepage/public/components/stack_app.tsx b/x-pack/plugins/search_homepage/public/components/stack_app.tsx new file mode 100644 index 0000000000000..ca18ac7112c09 --- /dev/null +++ b/x-pack/plugins/search_homepage/public/components/stack_app.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { SearchHomepageBody } from './search_homepage_body'; +import { SearchHomepageHeader } from './search_homepage_header'; + +export const App: React.FC = () => { + return ( + <> + + + + ); +}; diff --git a/x-pack/plugins/search_homepage/public/embeddable.tsx b/x-pack/plugins/search_homepage/public/embeddable.tsx new file mode 100644 index 0000000000000..ee69062ea3fe5 --- /dev/null +++ b/x-pack/plugins/search_homepage/public/embeddable.tsx @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { dynamic } from '@kbn/shared-ux-utility'; + +export const SearchHomepage = dynamic(async () => ({ + default: (await import('./components/stack_app')).App, +})); diff --git a/x-pack/plugins/search_homepage/public/feature_flags.ts b/x-pack/plugins/search_homepage/public/feature_flags.ts new file mode 100644 index 0000000000000..bea65a8e1548f --- /dev/null +++ b/x-pack/plugins/search_homepage/public/feature_flags.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IUiSettingsClient } from '@kbn/core/public'; +import { HOMEPAGE_FEATURE_FLAG_ID } from '../common'; + +export function isHomepageEnabled(uiSettings: IUiSettingsClient): boolean { + return uiSettings.get(HOMEPAGE_FEATURE_FLAG_ID, false); +} diff --git a/x-pack/plugins/search_homepage/public/hooks/use_kibana.ts b/x-pack/plugins/search_homepage/public/hooks/use_kibana.ts new file mode 100644 index 0000000000000..b22c7b4ed9d7f --- /dev/null +++ b/x-pack/plugins/search_homepage/public/hooks/use_kibana.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. + */ + +import { useKibana as _useKibana } from '@kbn/kibana-react-plugin/public'; +import { SearchHomepageServicesContext } from '../types'; + +export const useKibana = () => _useKibana(); diff --git a/x-pack/plugins/search_homepage/public/index.ts b/x-pack/plugins/search_homepage/public/index.ts new file mode 100644 index 0000000000000..b5133bb506406 --- /dev/null +++ b/x-pack/plugins/search_homepage/public/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializerContext } from '@kbn/core/public'; + +import { SearchHomepagePlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new SearchHomepagePlugin(initializerContext); +} + +export type { + SearchHomepagePluginSetup, + SearchHomepagePluginStart, + SearchHomepageAppInfo, +} from './types'; diff --git a/x-pack/plugins/search_homepage/public/plugin.ts b/x-pack/plugins/search_homepage/public/plugin.ts new file mode 100644 index 0000000000000..ebb3ef8ed822c --- /dev/null +++ b/x-pack/plugins/search_homepage/public/plugin.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + CoreSetup, + Plugin, + CoreStart, + AppMountParameters, + PluginInitializerContext, +} from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; +import { PLUGIN_ID } from '../common'; + +import { SearchHomepage } from './embeddable'; +import { isHomepageEnabled } from './feature_flags'; +import { + SearchHomepageConfigType, + SearchHomepagePluginSetup, + SearchHomepagePluginStart, + SearchHomepageAppPluginStartDependencies, + SearchHomepageAppInfo, +} from './types'; + +const appInfo: SearchHomepageAppInfo = { + id: PLUGIN_ID, + appRoute: '/app/elasticsearch/home', + title: i18n.translate('xpack.searchHomepage.appTitle', { defaultMessage: 'Home' }), +}; + +export class SearchHomepagePlugin + implements Plugin +{ + private readonly config: SearchHomepageConfigType; + constructor(initializerContext: PluginInitializerContext) { + this.config = initializerContext.config.get(); + } + + public setup( + core: CoreSetup + ) { + const result: SearchHomepagePluginSetup = { + app: appInfo, + isHomepageFeatureEnabled() { + return isHomepageEnabled(core.uiSettings); + }, + }; + if (!this.config.ui?.enabled) return result; + if (!isHomepageEnabled(core.uiSettings)) return result; + + core.application.register({ + ...result.app, + async mount({ element, history }: AppMountParameters) { + const { renderApp } = await import('./application'); + const [coreStart, depsStart] = await core.getStartServices(); + const startDeps: SearchHomepageAppPluginStartDependencies = { + ...depsStart, + history, + }; + + return renderApp(coreStart, startDeps, element); + }, + }); + + return result; + } + + public start(core: CoreStart) { + return { + app: appInfo, + isHomepageFeatureEnabled() { + return isHomepageEnabled(core.uiSettings); + }, + SearchHomepage, + }; + } +} diff --git a/x-pack/plugins/search_homepage/public/router.tsx b/x-pack/plugins/search_homepage/public/router.tsx new file mode 100644 index 0000000000000..e4db94ebde4ae --- /dev/null +++ b/x-pack/plugins/search_homepage/public/router.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { Route, Routes } from '@kbn/shared-ux-router'; + +import { SearchHomepagePage } from './components/search_homepage'; + +export const HomepageRouter = () => ( + + + + + +); diff --git a/x-pack/plugins/search_homepage/public/types.ts b/x-pack/plugins/search_homepage/public/types.ts new file mode 100644 index 0000000000000..de5283abfc61d --- /dev/null +++ b/x-pack/plugins/search_homepage/public/types.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ComponentProps, FC } from 'react'; +import type { CloudSetup } from '@kbn/cloud-plugin/public'; +import type { ConsolePluginStart } from '@kbn/console-plugin/public'; +import type { AppMountParameters, HttpStart } from '@kbn/core/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; +import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import type { App } from './components/stack_app'; + +export interface SearchHomepageConfigType { + ui: { + enabled: boolean; + }; +} + +export interface SearchHomepageAppInfo { + appRoute: string; + id: string; + title: string; +} + +export interface SearchHomepagePluginSetup { + /** + * Search Homepage shared information for the Kibana application. + * Used to ensure the stack and serverless apps have the same route + * and deep links. + */ + app: SearchHomepageAppInfo; + /** + * Checks if the Search Homepage feature flag is currently enabled. + * @returns true if Search Homepage feature is enabled + */ + isHomepageFeatureEnabled: () => boolean; +} + +export interface SearchHomepagePluginStart { + /** + * Search Homepage shared information for the Kibana application. + * Used to ensure the stack and serverless apps have the same route + * and deep links. + */ + app: SearchHomepageAppInfo; + /** + * Checks if the Search Homepage feature flag is currently enabled. + * @returns true if Search Homepage feature is enabled + */ + isHomepageFeatureEnabled: () => boolean; + /** + * SearchHomepage shared component, used to render the search homepage in + * the Stack search plugin + */ + SearchHomepage: FC>; +} + +export interface SearchHomepageAppPluginStartDependencies { + history: AppMountParameters['history']; + usageCollection?: UsageCollectionStart; + share: SharePluginStart; + console?: ConsolePluginStart; +} + +export interface SearchHomepageServicesContext { + http: HttpStart; + share: SharePluginStart; + cloud?: CloudSetup; + usageCollection?: UsageCollectionStart; + console?: ConsolePluginStart; +} diff --git a/x-pack/plugins/search_homepage/server/config.ts b/x-pack/plugins/search_homepage/server/config.ts new file mode 100644 index 0000000000000..3e068a719f046 --- /dev/null +++ b/x-pack/plugins/search_homepage/server/config.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from '@kbn/core/server'; + +export * from './types'; + +const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), + ui: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), +}); + +export type SearchHomepageConfig = TypeOf; + +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + ui: true, + }, + schema: configSchema, +}; diff --git a/x-pack/plugins/search_homepage/server/index.ts b/x-pack/plugins/search_homepage/server/index.ts new file mode 100644 index 0000000000000..864af85c0a2fb --- /dev/null +++ b/x-pack/plugins/search_homepage/server/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializerContext } from '@kbn/core/server'; + +export { config } from './config'; + +export async function plugin(initializerContext: PluginInitializerContext) { + const { SearchHomepagePlugin } = await import('./plugin'); + return new SearchHomepagePlugin(initializerContext); +} + +export type { SearchHomepagePluginSetup, SearchHomepagePluginStart } from './types'; diff --git a/x-pack/plugins/search_homepage/server/plugin.ts b/x-pack/plugins/search_homepage/server/plugin.ts new file mode 100644 index 0000000000000..f446ba4e41fd3 --- /dev/null +++ b/x-pack/plugins/search_homepage/server/plugin.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server'; + +import { SearchHomepagePluginSetup, SearchHomepagePluginStart } from './types'; + +export class SearchHomepagePlugin + implements Plugin +{ + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + public setup(core: CoreSetup<{}, SearchHomepagePluginStart>) { + this.logger.debug('searchHomepage: Setup'); + return {}; + } + + public start(core: CoreStart) { + return {}; + } +} diff --git a/x-pack/plugins/search_homepage/server/types.ts b/x-pack/plugins/search_homepage/server/types.ts new file mode 100644 index 0000000000000..c4e5d46959422 --- /dev/null +++ b/x-pack/plugins/search_homepage/server/types.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface SearchHomepagePluginSetup {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface SearchHomepagePluginStart {} diff --git a/x-pack/plugins/search_homepage/tsconfig.json b/x-pack/plugins/search_homepage/tsconfig.json new file mode 100644 index 0000000000000..9f084b32f7d3b --- /dev/null +++ b/x-pack/plugins/search_homepage/tsconfig.json @@ -0,0 +1,30 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + }, + "include": [ + "__mocks__/**/*", + "common/**/*", + "public/**/*", + "server/**/*", + ], + "kbn_references": [ + "@kbn/core", + "@kbn/react-kibana-context-render", + "@kbn/kibana-react-plugin", + "@kbn/i18n-react", + "@kbn/shared-ux-router", + "@kbn/shared-ux-page-kibana-template", + "@kbn/shared-ux-utility", + "@kbn/i18n", + "@kbn/cloud-plugin", + "@kbn/console-plugin", + "@kbn/share-plugin", + "@kbn/usage-collection-plugin", + "@kbn/config-schema", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/x-pack/plugins/serverless_search/kibana.jsonc b/x-pack/plugins/serverless_search/kibana.jsonc index 3a98a87c032a4..04002ee897cf4 100644 --- a/x-pack/plugins/serverless_search/kibana.jsonc +++ b/x-pack/plugins/serverless_search/kibana.jsonc @@ -29,6 +29,7 @@ "optionalPlugins": [ "indexManagement", "searchConnectors", + "searchHomepage", "searchInferenceEndpoints", "usageCollection" ], diff --git a/x-pack/plugins/serverless_search/public/navigation_tree.ts b/x-pack/plugins/serverless_search/public/navigation_tree.ts index d21eee8de9c19..f5618e8b83e05 100644 --- a/x-pack/plugins/serverless_search/public/navigation_tree.ts +++ b/x-pack/plugins/serverless_search/public/navigation_tree.ts @@ -9,7 +9,7 @@ import type { NavigationTreeDefinition } from '@kbn/core-chrome-browser'; import { i18n } from '@kbn/i18n'; import { CONNECTORS_LABEL } from '../common/i18n_string'; -export const navigationTree: NavigationTreeDefinition = { +export const navigationTree = (useSearchHomepage: boolean = false): NavigationTreeDefinition => ({ body: [ { type: 'navGroup', @@ -25,7 +25,7 @@ export const navigationTree: NavigationTreeDefinition = { title: i18n.translate('xpack.serverlessSearch.nav.home', { defaultMessage: 'Home', }), - link: 'serverlessElasticsearch', + link: useSearchHomepage ? 'searchHomepage' : 'serverlessElasticsearch', spaceBefore: 'm', }, { @@ -149,4 +149,4 @@ export const navigationTree: NavigationTreeDefinition = { ], }, ], -}; +}); diff --git a/x-pack/plugins/serverless_search/public/plugin.ts b/x-pack/plugins/serverless_search/public/plugin.ts index d9019f911444a..e72e1a4575079 100644 --- a/x-pack/plugins/serverless_search/public/plugin.ts +++ b/x-pack/plugins/serverless_search/public/plugin.ts @@ -43,6 +43,9 @@ export class ServerlessSearchPlugin core: CoreSetup, setupDeps: ServerlessSearchPluginSetupDependencies ): ServerlessSearchPluginSetup { + const { searchHomepage } = setupDeps; + const useSearchHomepage = searchHomepage && searchHomepage.isHomepageFeatureEnabled(); + const queryClient = new QueryClient({ mutationCache: new MutationCache({ onError: (error) => { @@ -69,6 +72,24 @@ export class ServerlessSearchPlugin }, }), }); + if (useSearchHomepage) { + core.application.register({ + id: 'serverlessHomeRedirect', + title: i18n.translate('xpack.serverlessSearch.app.home.title', { + defaultMessage: 'Home', + }), + appRoute: '/app/elasticsearch', + euiIconType: 'logoElastic', + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + visibleIn: [], + async mount({}: AppMountParameters) { + const [coreStart] = await core.getStartServices(); + coreStart.application.navigateToApp('searchHomepage'); + return () => {}; + }, + }); + } + core.application.register({ id: 'serverlessElasticsearch', title: i18n.translate('xpack.serverlessSearch.app.elasticsearch.title', { @@ -76,7 +97,7 @@ export class ServerlessSearchPlugin }), euiIconType: 'logoElastic', category: DEFAULT_APP_CATEGORIES.enterpriseSearch, - appRoute: '/app/elasticsearch', + appRoute: useSearchHomepage ? '/app/elasticsearch/getting_started' : '/app/elasticsearch', async mount({ element, history }: AppMountParameters) { const { renderApp } = await import('./application/elasticsearch'); const [coreStart, services] = await core.getStartServices(); @@ -121,10 +142,12 @@ export class ServerlessSearchPlugin core: CoreStart, services: ServerlessSearchPluginStartDependencies ): ServerlessSearchPluginStart { - const { serverless, management, indexManagement, security } = services; - serverless.setProjectHome('/app/elasticsearch'); + const { serverless, management, indexManagement, security, searchHomepage } = services; + const useSearchHomepage = searchHomepage && searchHomepage.isHomepageFeatureEnabled(); + + serverless.setProjectHome(useSearchHomepage ? '/app/elasticsearch/home' : '/app/elasticsearch'); - const navigationTree$ = of(navigationTree); + const navigationTree$ = of(navigationTree(searchHomepage?.isHomepageFeatureEnabled() ?? false)); serverless.initNavigation('search', navigationTree$, { dataTestSubj: 'svlSearchSideNav' }); const extendCardNavDefinitions = serverless.getNavigationCards( diff --git a/x-pack/plugins/serverless_search/public/types.ts b/x-pack/plugins/serverless_search/public/types.ts index e4eab5fbfd61d..d3011210c524f 100644 --- a/x-pack/plugins/serverless_search/public/types.ts +++ b/x-pack/plugins/serverless_search/public/types.ts @@ -5,16 +5,20 @@ * 2.0. */ -import { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public'; -import { ConsolePluginStart } from '@kbn/console-plugin/public'; -import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public'; -import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public'; -import { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public'; -import { SecurityPluginStart } from '@kbn/security-plugin/public'; -import { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public'; -import { SharePluginStart } from '@kbn/share-plugin/public'; -import { IndexManagementPluginStart } from '@kbn/index-management-plugin/public'; +import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public'; +import type { ConsolePluginStart } from '@kbn/console-plugin/public'; +import type { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public'; +import type { SearchPlaygroundPluginStart } from '@kbn/search-playground/public'; +import type { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; +import type { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; +import type { IndexManagementPluginStart } from '@kbn/index-management-plugin/public'; import type { DiscoverSetup } from '@kbn/discover-plugin/public'; +import type { + SearchHomepagePluginSetup, + SearchHomepagePluginStart, +} from '@kbn/search-homepage/public'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ServerlessSearchPluginSetup {} @@ -27,6 +31,7 @@ export interface ServerlessSearchPluginSetupDependencies { management: ManagementSetup; serverless: ServerlessPluginSetup; discover: DiscoverSetup; + searchHomepage?: SearchHomepagePluginSetup; } export interface ServerlessSearchPluginStartDependencies { @@ -39,4 +44,5 @@ export interface ServerlessSearchPluginStartDependencies { serverless: ServerlessPluginStart; share: SharePluginStart; indexManagement?: IndexManagementPluginStart; + searchHomepage?: SearchHomepagePluginStart; } diff --git a/x-pack/plugins/serverless_search/tsconfig.json b/x-pack/plugins/serverless_search/tsconfig.json index 8cf2dec121d46..418dcb5fc6f5c 100644 --- a/x-pack/plugins/serverless_search/tsconfig.json +++ b/x-pack/plugins/serverless_search/tsconfig.json @@ -50,5 +50,6 @@ "@kbn/react-kibana-context-render", "@kbn/search-playground", "@kbn/search-inference-endpoints", + "@kbn/search-homepage", ] } diff --git a/x-pack/test_serverless/functional/page_objects/index.ts b/x-pack/test_serverless/functional/page_objects/index.ts index f1604d48508e2..94e02f9c5e455 100644 --- a/x-pack/test_serverless/functional/page_objects/index.ts +++ b/x-pack/test_serverless/functional/page_objects/index.ts @@ -21,6 +21,7 @@ import { SvlRuleDetailsPageProvider } from './svl_rule_details_ui_page'; import { SvlSearchConnectorsPageProvider } from './svl_search_connectors_page'; import { SvlManagementPageProvider } from './svl_management_page'; import { SvlIngestPipelines } from './svl_ingest_pipelines'; +import { SvlSearchHomePageProvider } from './svl_search_homepage'; export const pageObjects = { ...xpackFunctionalPageObjects, @@ -38,4 +39,5 @@ export const pageObjects = { svlRuleDetailsUI: SvlRuleDetailsPageProvider, svlManagementPage: SvlManagementPageProvider, svlIngestPipelines: SvlIngestPipelines, + svlSearchHomePage: SvlSearchHomePageProvider, }; diff --git a/x-pack/test_serverless/functional/page_objects/svl_search_homepage.ts b/x-pack/test_serverless/functional/page_objects/svl_search_homepage.ts new file mode 100644 index 0000000000000..eeb1b6de731f9 --- /dev/null +++ b/x-pack/test_serverless/functional/page_objects/svl_search_homepage.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function SvlSearchHomePageProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + + return { + async expectToBeOnHomepage() { + expect(await browser.getCurrentUrl()).contain('/app/elasticsearch/home'); + }, + async expectToNotBeOnHomepage() { + expect(await browser.getCurrentUrl()).not.contain('/app/elasticsearch/home'); + }, + async expectHomepageHeader() { + await testSubjects.existOrFail('search-homepage-header', { timeout: 2000 }); + }, + }; +} diff --git a/x-pack/test_serverless/functional/services/index.ts b/x-pack/test_serverless/functional/services/index.ts index a1112232377cd..c63a16b4402f1 100644 --- a/x-pack/test_serverless/functional/services/index.ts +++ b/x-pack/test_serverless/functional/services/index.ts @@ -16,6 +16,7 @@ import { SvlCommonScreenshotsProvider } from './svl_common_screenshots'; import { SvlCasesServiceProvider } from '../../api_integration/services/svl_cases'; import { MachineLearningProvider } from './ml'; import { LogsSynthtraceProvider } from './log'; +import { UISettingsServiceProvider } from './ui_settings'; export const services = { // deployment agnostic FTR services @@ -30,6 +31,7 @@ export const services = { svlCommonScreenshots: SvlCommonScreenshotsProvider, svlCases: SvlCasesServiceProvider, svlMl: MachineLearningProvider, + uiSettings: UISettingsServiceProvider, // log services svlLogsSynthtraceClient: LogsSynthtraceProvider, }; diff --git a/x-pack/test_serverless/functional/services/ui_settings.ts b/x-pack/test_serverless/functional/services/ui_settings.ts new file mode 100644 index 0000000000000..337930790489d --- /dev/null +++ b/x-pack/test_serverless/functional/services/ui_settings.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; +import { RoleCredentials } from '../../shared/services'; + +export function UISettingsServiceProvider({ getService }: FtrProviderContext) { + const svlCommonApi = getService('svlCommonApi'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + return { + async setUiSetting(role: RoleCredentials, settingId: string, value: unknown) { + await supertestWithoutAuth + .post(`/internal/kibana/settings/${settingId}`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(role.apiKeyHeader) + .send({ value }) + .expect(200); + }, + async deleteUISetting(role: RoleCredentials, settingId: string) { + await supertestWithoutAuth + .delete(`/internal/kibana/settings/${settingId}`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(role.apiKeyHeader) + .expect(200); + }, + }; +} diff --git a/x-pack/test_serverless/functional/test_suites/search/index.ts b/x-pack/test_serverless/functional/test_suites/search/index.ts index 455acc0404429..8c3cfd83e04e9 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.ts @@ -23,5 +23,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./playground_overview')); loadTestFile(require.resolve('./ml')); + loadTestFile(require.resolve('./search_homepage')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/search/search_homepage.ts b/x-pack/test_serverless/functional/test_suites/search/search_homepage.ts new file mode 100644 index 0000000000000..3138e0e7f0242 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/search_homepage.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; +import { RoleCredentials } from '../../../shared/services'; + +import { testHasEmbeddedConsole } from './embedded_console'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const pageObjects = getPageObjects(['svlCommonPage', 'svlCommonNavigation', 'svlSearchHomePage']); + const svlUserManager = getService('svlUserManager'); + const uiSettings = getService('uiSettings'); + let roleAuthc: RoleCredentials; + + const HOMEPAGE_FF_UI_SETTING = 'searchHomepage:homepageEnabled'; + describe('Search Homepage', function () { + this.tags('skipMKI'); + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + // Enable Homepage Feature Flag + await uiSettings.setUiSetting(roleAuthc, HOMEPAGE_FF_UI_SETTING, true); + + await pageObjects.svlCommonPage.login(); + }); + + after(async () => { + if (!roleAuthc) return; + + // Disable Homepage Feature Flag + await uiSettings.deleteUISetting(roleAuthc, HOMEPAGE_FF_UI_SETTING); + + await pageObjects.svlCommonPage.forceLogout(); + }); + + it('has search homepage with Home sidenav', async () => { + pageObjects.svlSearchHomePage.expectToBeOnHomepage(); + pageObjects.svlSearchHomePage.expectHomepageHeader(); + // Navigate to another page + await pageObjects.svlCommonNavigation.sidenav.clickLink({ + deepLinkId: 'serverlessConnectors', + }); + pageObjects.svlSearchHomePage.expectToNotBeOnHomepage(); + // Click Home in Side nav + await pageObjects.svlCommonNavigation.sidenav.clickLink({ + deepLinkId: 'searchHomepage', + }); + pageObjects.svlSearchHomePage.expectToBeOnHomepage(); + }); + + it('has embedded dev console', async () => { + testHasEmbeddedConsole(pageObjects); + }); + }); +} diff --git a/yarn.lock b/yarn.lock index 64ba753c57695..d1dec3cae024a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6056,6 +6056,10 @@ version "0.0.0" uid "" +"@kbn/search-homepage@link:x-pack/plugins/search_homepage": + version "0.0.0" + uid "" + "@kbn/search-index-documents@link:packages/kbn-search-index-documents": version "0.0.0" uid "" From 45b8c7e1519f83d3b942e37c872a1700ac9f119a Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Wed, 19 Jun 2024 13:04:45 +0200 Subject: [PATCH 108/127] [ML] AIOps: Fix log rate analysis alert details page embedding. (#186371) ## Summary Fixes the log rate analysis embedding in the O11y alert details page, a regression caused by #180969. The refactor in the linked PR moved the data fetching for the histogram chart higher up in the component tree and it was then missing from the embedded variant. ### Checklist - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../log_rate_analysis_content.tsx | 6 +- .../log_rate_analysis_content_wrapper.tsx | 6 +- ...ate_analysis_document_count_chart_data.tsx | 71 +++++++++++++++++++ 3 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_document_count_chart_data.tsx diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx index a62191ed5a02e..abeb4c603b4e6 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx @@ -8,7 +8,6 @@ import { isEqual } from 'lodash'; import React, { useCallback, useEffect, useMemo, useRef, type FC } from 'react'; import { EuiButton, EuiEmptyPrompt, EuiHorizontalRule, EuiPanel } from '@elastic/eui'; -import type { Moment } from 'moment'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { BarStyleAccessor } from '@elastic/charts/dist/chart_types/xy_chart/utils/specs'; @@ -37,7 +36,7 @@ import { type LogRateAnalysisResultsData, } from '../log_rate_analysis_results'; -const DEFAULT_SEARCH_QUERY: estypes.QueryDslQueryContainer = { match_all: {} }; +export const DEFAULT_SEARCH_QUERY: estypes.QueryDslQueryContainer = { match_all: {} }; const DEFAULT_SEARCH_BAR_QUERY: estypes.QueryDslQueryContainer = { bool: { filter: [], @@ -51,8 +50,6 @@ const DEFAULT_SEARCH_BAR_QUERY: estypes.QueryDslQueryContainer = { }; export interface LogRateAnalysisContentProps { - /** Optional time range override */ - timeRange?: { min: Moment; max: Moment }; /** Elasticsearch query to pass to analysis endpoint */ esSearchQuery?: estypes.QueryDslQueryContainer; /** Optional color override for the default bar color for charts */ @@ -68,7 +65,6 @@ export interface LogRateAnalysisContentProps { } export const LogRateAnalysisContent: FC = ({ - timeRange, esSearchQuery = DEFAULT_SEARCH_QUERY, barColorOverride, barHighlightColorOverride, diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx index e9f623ecf0f17..dace975115deb 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx @@ -27,6 +27,7 @@ import { AIOPS_STORAGE_KEYS } from '../../../types/storage'; import type { LogRateAnalysisResultsData } from '../log_rate_analysis_results'; +import { LogRateAnalysisDocumentCountChartData } from './log_rate_analysis_document_count_chart_data'; import { LogRateAnalysisContent } from './log_rate_analysis_content'; const localStorage = new Storage(window.localStorage); @@ -93,9 +94,12 @@ export const LogRateAnalysisContentWrapper: FC - + = ({ timeRange, esSearchQuery }) => { + const { dataView } = useDataSource(); + + const currentSelectedGroup = useCurrentSelectedGroup(); + const currentSelectedSignificantItem = useCurrentSelectedSignificantItem(); + const dispatch = useAppDispatch(); + + const { documentStats, earliest, latest, intervalMs } = useData( + dataView, + 'log_rate_analysis', + esSearchQuery ?? DEFAULT_SEARCH_QUERY, + undefined, + currentSelectedSignificantItem, + currentSelectedGroup, + undefined, + true, + timeRange + ); + + // TODO Since `useData` isn't just used within Log Rate Analysis, this is a bit of + // a workaround to pass the result on to the redux store. At least this ensures + // we now use `useData` only once across Log Rate Analysis! Originally `useData` + // was quite general, but over time it got quite some specific features used + // across Log Rate Analysis and Pattern Analysis. We discussed that we should + // split this up into more specific hooks. + useEffect(() => { + dispatch( + setDocumentCountChartData({ + earliest, + latest, + intervalMs, + documentStats, + }) + ); + }, [documentStats, dispatch, earliest, intervalMs, latest]); + + return null; +}; From 36c2d128a06077f328a81adb3b7ce12b4af3dc15 Mon Sep 17 00:00:00 2001 From: Bena Kansara <69037875+benakansara@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:49:32 +0200 Subject: [PATCH 109/127] [Custom threshold/Metric threshold] Use emotion instead of styled component for auto suggestion (#186422) Fixes https://github.com/elastic/kibana/issues/186248 for Custom threshold and Metric threshold (custom equation use case) rules ### Custom threshold rule https://github.com/elastic/kibana/assets/69037875/dd25a874-4c7b-4cb2-9319-82ac5977e5d9 ### Metric threshold rule (Custom equation) https://github.com/elastic/kibana/assets/69037875/14cb0394-632c-418c-813e-6c4eef6e44fb --------- Co-authored-by: jennypavlova --- .../metrics_explorer/components/kuery_bar.tsx | 6 +- .../autocomplete_field/autocomplete_field.tsx | 53 +++--- .../autocomplete_field/suggestion_item.tsx | 151 ++++++++++-------- .../components/rule_kql_filter/kuery_bar.tsx | 4 + 4 files changed, 124 insertions(+), 90 deletions(-) diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx index b6918ab140df1..a75940714dec6 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/kuery_bar.tsx @@ -9,9 +9,10 @@ import { i18n } from '@kbn/i18n'; import { fromKueryExpression } from '@kbn/es-query'; import React, { useEffect, useState } from 'react'; import { QuerySuggestion } from '@kbn/unified-search-plugin/public'; +import { AutocompleteField } from '@kbn/observability-plugin/public'; +import { useEuiTheme } from '@elastic/eui'; import { useMetricsDataViewContext } from '../../../../containers/metrics_source'; import { WithKueryAutocompletion } from '../../../../containers/with_kuery_autocompletion'; -import { AutocompleteField } from '../../../../components/autocomplete_field'; type LoadSuggestionsFn = ( e: string, @@ -58,6 +59,8 @@ export const MetricsExplorerKueryBar = ({ } }, [value]); + const { euiTheme } = useEuiTheme(); + const handleChange = (query: string) => { setValidation(validateQuery(query)); setDraftQuery(query); @@ -87,6 +90,7 @@ export const MetricsExplorerKueryBar = ({ placeholder={placeholder || defaultPlaceholder} suggestions={suggestions} value={draftQuery} + theme={euiTheme} /> )} diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx index 4aaa44e742108..e8545276c572a 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx @@ -5,12 +5,12 @@ * 2.0. */ -import { EuiFieldSearch, EuiOutsideClickDetector, EuiPanel } from '@elastic/eui'; +import { EuiFieldSearch, EuiOutsideClickDetector, EuiPanel, EuiThemeComputed } from '@elastic/eui'; import React from 'react'; import { QuerySuggestion } from '@kbn/unified-search-plugin/public'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; - +import { css } from '@emotion/react'; import { SuggestionItem } from './suggestion_item'; + export type StateUpdater = ( prevState: Readonly, prevProps: Readonly @@ -34,6 +34,7 @@ interface AutocompleteFieldProps { autoFocus?: boolean; 'aria-label'?: string; compressed?: boolean; + theme?: EuiThemeComputed; } interface AutocompleteFieldState { @@ -64,12 +65,17 @@ export class AutocompleteField extends React.Component< disabled, 'aria-label': ariaLabel, compressed, + theme, } = this.props; const { areSuggestionsVisible, selectedIndex } = this.state; return ( - +
{areSuggestionsVisible && !isLoadingSuggestions && suggestions.length > 0 ? ( - + {suggestions.map((suggestion, suggestionIndex) => ( ))} - + ) : null} - +
); } @@ -310,20 +330,3 @@ const withUnfocused = (state: AutocompleteFieldState) => ({ ...state, isFocused: false, }); - -const AutocompleteContainer = euiStyled.div` - position: relative; -`; - -const SuggestionsPanel = euiStyled(EuiPanel).attrs(() => ({ - paddingSize: 'none', - hasShadow: true, -}))` - position: absolute; - width: 100%; - margin-top: 2px; - overflow-x: hidden; - overflow-y: scroll; - z-index: ${(props) => props.theme.eui.euiZLevel1}; - max-height: 322px; -`; diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/suggestion_item.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/suggestion_item.tsx index 67e4c879c7243..2eb5165b20e89 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/suggestion_item.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/suggestion_item.tsx @@ -6,29 +6,96 @@ */ import React from 'react'; -import { EuiIcon } from '@elastic/eui'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { EuiIcon, euiPaletteColorBlind, EuiThemeComputed, useEuiTheme } from '@elastic/eui'; import { QuerySuggestion, QuerySuggestionTypes } from '@kbn/unified-search-plugin/public'; import { transparentize } from 'polished'; +import { css } from '@emotion/react'; interface Props { isSelected?: boolean; onClick?: React.MouseEventHandler; onMouseEnter?: React.MouseEventHandler; + onKeyDown?: React.KeyboardEventHandler; suggestion: QuerySuggestion; } export function SuggestionItem(props: Props) { - const { isSelected, onClick, onMouseEnter, suggestion } = props; + const { isSelected, onClick, onMouseEnter, onKeyDown, suggestion } = props; + const { euiTheme } = useEuiTheme(); + + const suggestionItemContainerCss = ` + display: flex; + flex-direction: row; + font-size: ${euiTheme.font.scale.s}; + height: ${euiTheme.size.xl}; + white-space: nowrap; + background-color: ${isSelected ? euiTheme.colors.lightestShade : 'transparent'}; + `; + + const suggestionItemFieldCss = ` + align-items: center; + cursor: pointer; + display: flex; + flex-direction: row; + height: ${euiTheme.size.xl}; + padding: ${euiTheme.size.xs}; + `; + + const suggestionItemIconFieldCss = ` + background-color: ${transparentize(0.9, getEuiIconColor(euiTheme, suggestion.type))}; + color: ${getEuiIconColor(euiTheme, suggestion.type)}; + flex: 0 0 auto; + justify-content: center; + width: ${euiTheme.size.xl}; + `; + + const suggestionItemTextFieldCss = ` + flex: 2 0 0; + font-family: ${euiTheme.font.familyCode}; + `; + + const suggestionItemDescriptionFieldCss = ` + flex: 3 0 0; + p { + display: inline; + span { + font-family: ${euiTheme.font.familyCode}; + } + } + `; return ( - - +
+
- - {suggestion.text} - {suggestion.description} - +
+
+ {suggestion.text} +
+
+ {suggestion.description} +
+
); } @@ -36,55 +103,6 @@ SuggestionItem.defaultProps = { isSelected: false, }; -const SuggestionItemContainer = euiStyled.div<{ - isSelected?: boolean; -}>` - display: flex; - flex-direction: row; - font-size: ${(props) => props.theme.eui.euiFontSizeS}; - height: ${(props) => props.theme.eui.euiSizeXL}; - white-space: nowrap; - background-color: ${(props) => - props.isSelected ? props.theme.eui.euiColorLightestShade : 'transparent'}; -`; - -const SuggestionItemField = euiStyled.div` - align-items: center; - cursor: pointer; - display: flex; - flex-direction: row; - height: ${(props) => props.theme.eui.euiSizeXL}; - padding: ${(props) => props.theme.eui.euiSizeXS}; -`; - -const SuggestionItemIconField = euiStyled(SuggestionItemField)<{ - suggestionType: QuerySuggestionTypes; -}>` - background-color: ${(props) => - transparentize(0.9, getEuiIconColor(props.theme, props.suggestionType))}; - color: ${(props) => getEuiIconColor(props.theme, props.suggestionType)}; - flex: 0 0 auto; - justify-content: center; - width: ${(props) => props.theme.eui.euiSizeXL}; -`; - -const SuggestionItemTextField = euiStyled(SuggestionItemField)` - flex: 2 0 0; - font-family: ${(props) => props.theme.eui.euiCodeFontFamily}; -`; - -const SuggestionItemDescriptionField = euiStyled(SuggestionItemField)` - flex: 3 0 0; - - p { - display: inline; - - span { - font-family: ${(props) => props.theme.eui.euiCodeFontFamily}; - } - } -`; - const getEuiIconType = (suggestionType: QuerySuggestionTypes) => { switch (suggestionType) { case QuerySuggestionTypes.Field: @@ -102,18 +120,23 @@ const getEuiIconType = (suggestionType: QuerySuggestionTypes) => { } }; -const getEuiIconColor = (theme: any, suggestionType: QuerySuggestionTypes): string => { +const getEuiIconColor = ( + euiTheme: EuiThemeComputed, + suggestionType: QuerySuggestionTypes +): string => { + const palette = euiPaletteColorBlind(); + switch (suggestionType) { case QuerySuggestionTypes.Field: - return theme?.eui.euiColorVis7; + return palette[7]; case QuerySuggestionTypes.Value: - return theme?.eui.euiColorVis0; + return palette[0]; case QuerySuggestionTypes.Operator: - return theme?.eui.euiColorVis1; + return palette[1]; case QuerySuggestionTypes.Conjunction: - return theme?.eui.euiColorVis2; + return palette[2]; case QuerySuggestionTypes.RecentSearch: default: - return theme?.eui.euiColorMediumShade; + return euiTheme.colors.mediumShade; } }; diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx index 9c16d4d7b69af..26115ec331021 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx @@ -10,6 +10,7 @@ import React, { useEffect, useState } from 'react'; import { DataViewBase } from '@kbn/es-query'; import { QuerySuggestion } from '@kbn/unified-search-plugin/public'; +import { useEuiTheme } from '@elastic/eui'; import { WithKueryAutocompletion } from './with_kuery_autocompletion'; import { AutocompleteField } from './autocomplete_field'; @@ -59,6 +60,8 @@ export function RuleFlyoutKueryBar({ } }, [value]); + const { euiTheme } = useEuiTheme(); + const handleChange = (query: string) => { setValidation(validateQuery(query)); setDraftQuery(query); @@ -86,6 +89,7 @@ export function RuleFlyoutKueryBar({ placeholder={placeholder} suggestions={suggestions} value={draftQuery} + theme={euiTheme} /> )} From 16a3749837127036179b4df551b324692ec55c33 Mon Sep 17 00:00:00 2001 From: Tiago Vila Verde Date: Wed, 19 Jun 2024 14:04:50 +0200 Subject: [PATCH 110/127] [Security Solution][Entity Analytics] Adding Asset Criticality column to All Hosts tab in Explore pages (#186375) This PR adds a new column for Asset Criticality to the "All hosts" tab in the Explore/Hosts page. If any of the hosts has criticality data assigned, it will be displayed in the new column. If no criticality has been assigned, the field is left blank. ![Screenshot 2024-06-18 at 15 00 46](https://github.com/elastic/kibana/assets/2423976/dc6e76c9-ceed-4da6-905c-b374181fe0f3) ### How to test 1. Make sure you have test data with Asset Criticality. - Either use the [datagen tool](https://github.com/elastic/security-documents-generator) or just make sure to assign criticality to already existing hosts 2. Enable Asset Criticality settings in `Stack Management > Kibana > Advanced Settings` 3. Navigate to `Explore > Hosts > All Hosts` --- .../search_strategy/asset_criticality/all.ts | 20 +++++ .../hosts/components/hosts_table/columns.tsx | 24 +++++- .../components/hosts_table/index.test.tsx | 60 +++++++++++++++ .../hosts/components/hosts_table/index.tsx | 23 ++++-- .../components/hosts_table/translations.ts | 7 ++ .../query.asset_criticality.dsl.ts | 49 +++++++++++++ .../factory/hosts/all/index.ts | 73 +++++++++++++------ 7 files changed, 228 insertions(+), 28 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/asset_criticality/all.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/asset_criticality/query.asset_criticality.dsl.ts diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/asset_criticality/all.ts b/x-pack/plugins/security_solution/common/api/search_strategy/asset_criticality/all.ts new file mode 100644 index 0000000000000..cbbc885cc6091 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/asset_criticality/all.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; +import { requestBasicOptionsSchema } from '../model/request_basic_options'; + +export const assetCriticalityRequestOptionsSchema = requestBasicOptionsSchema.extend({ + pagination: z + .object({ + cursorStart: z.number(), + querySize: z.number(), + }) + .optional(), +}); + +export type AssetCriticalityRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/columns.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/columns.tsx index 270a10b52155a..6f8e3ad587a0d 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/columns.tsx @@ -7,6 +7,8 @@ import { EuiIcon, EuiLink, EuiText, EuiToolTip } from '@elastic/eui'; import React from 'react'; +import type { CriticalityLevelWithUnassigned } from '../../../../../common/entity_analytics/asset_criticality/types'; +import { AssetCriticalityBadge } from '../../../../entity_analytics/components/asset_criticality'; import { SecurityCellActions, CellActionsMode, @@ -25,7 +27,8 @@ import { ENTITY_RISK_LEVEL } from '../../../../entity_analytics/components/risk_ export const getHostsColumns = ( showRiskColumn: boolean, - dispatchSeverityUpdate: (s: RiskSeverity) => void + dispatchSeverityUpdate: (s: RiskSeverity) => void, + isAssetCriticalityEnabled: boolean ): HostsTableColumns => { const columns: HostsTableColumns = [ { @@ -163,5 +166,24 @@ export const getHostsColumns = ( }); } + if (isAssetCriticalityEnabled) { + columns.push({ + field: 'node.criticality', + name: i18n.ASSET_CRITICALITY, + truncateText: false, + mobileOptions: { show: true }, + sortable: false, + render: (assetCriticality: CriticalityLevelWithUnassigned) => { + if (!assetCriticality) return getEmptyTagValue(); + return ( + + ); + }, + }); + } + return columns; }; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.test.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.test.tsx index d46182ca7f4d9..8d20fed91a66a 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.test.tsx @@ -46,6 +46,16 @@ jest.mock('../../../../helper_hooks', () => ({ useHasSecurityCapability: () => mockUseHasSecurityCapability(), })); +const mockUseUiSetting = jest.fn().mockReturnValue([false]); + +jest.mock('@kbn/kibana-react-plugin/public', () => { + const original = jest.requireActual('@kbn/kibana-react-plugin/public'); + return { + ...original, + useUiSetting$: () => mockUseUiSetting(), + }; +}); + describe('Hosts Table', () => { const loadPage = jest.fn(); const store = createMockStore(); @@ -145,6 +155,56 @@ describe('Hosts Table', () => { expect(queryByTestId('tableHeaderCell_node.riskScore_4')).not.toBeInTheDocument(); }); + test('it renders "Asset Criticality" column when "isPlatinumOrTrialLicense" is truthy, user has risk-entity capability and Asset Criticality is enabled in Kibana settings', () => { + mockUseMlCapabilities.mockReturnValue({ isPlatinumOrTrialLicense: true }); + mockUseHasSecurityCapability.mockReturnValue(true); + mockUseUiSetting.mockReturnValue([true]); + + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('tableHeaderCell_node.criticality_5')).toBeInTheDocument(); + }); + + test('it does not render "Asset Criticality" column when Asset Criticality is not enabled in Kibana settings', () => { + mockUseMlCapabilities.mockReturnValue({ isPlatinumOrTrialLicense: true }); + mockUseHasSecurityCapability.mockReturnValue(true); + mockUseUiSetting.mockReturnValue([false]); + + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('tableHeaderCell_node.criticality_5')).not.toBeInTheDocument(); + }); + describe('Sorting on Table', () => { let wrapper: ReturnType; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx index 3c76bc5dcbf9c..ef9a368dac370 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx @@ -9,6 +9,8 @@ import React, { useMemo, useCallback } from 'react'; import { useDispatch } from 'react-redux'; import type { HostEcs, OsEcs } from '@kbn/securitysolution-ecs'; +import { useUiSetting$ } from '@kbn/kibana-react-plugin/public'; +import type { CriticalityLevelWithUnassigned } from '../../../../../common/entity_analytics/asset_criticality/types'; import { HostsFields } from '../../../../../common/api/search_strategy/hosts/model/sort'; import type { Columns, @@ -27,7 +29,10 @@ import type { HostsSortField, } from '../../../../../common/search_strategy/security_solution/hosts'; import type { Direction, RiskSeverity } from '../../../../../common/search_strategy'; -import { SecurityPageName } from '../../../../../common/constants'; +import { + ENABLE_ASSET_CRITICALITY_SETTING, + SecurityPageName, +} from '../../../../../common/constants'; import { HostsTableType } from '../../store/model'; import { useNavigateTo } from '../../../../common/lib/kibana/hooks'; import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; @@ -53,7 +58,8 @@ export type HostsTableColumns = [ Columns, Columns, Columns, - Columns? + Columns?, + Columns? ]; const rowItems: ItemsPerRow[] = [ @@ -153,15 +159,22 @@ const HostsTableComponent: React.FC = ({ [dispatch, navigateTo, type] ); + const [isAssetCriticalityEnabled] = useUiSetting$(ENABLE_ASSET_CRITICALITY_SETTING); + const hostsColumns = useMemo( () => getHostsColumns( isPlatinumOrTrialLicense && hasEntityAnalyticsCapability, - dispatchSeverityUpdate + dispatchSeverityUpdate, + isAssetCriticalityEnabled ), - [dispatchSeverityUpdate, isPlatinumOrTrialLicense, hasEntityAnalyticsCapability] + [ + dispatchSeverityUpdate, + isPlatinumOrTrialLicense, + hasEntityAnalyticsCapability, + isAssetCriticalityEnabled, + ] ); - const sorting = useMemo(() => getSorting(sortField, direction), [sortField, direction]); return ( diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts index 1f81968213b45..c6cc085a61b0b 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/translations.ts @@ -60,3 +60,10 @@ export const ROWS_10 = i18n.translate('xpack.securitySolution.hostsTable.rows', values: { numRows: 10 }, defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}', }); + +export const ASSET_CRITICALITY = i18n.translate( + 'xpack.securitySolution.hostsTable.assetCriticality', + { + defaultMessage: 'Asset criticality', + } +); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/asset_criticality/query.asset_criticality.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/asset_criticality/query.asset_criticality.dsl.ts new file mode 100644 index 0000000000000..8b081ecd951d7 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/asset_criticality/query.asset_criticality.dsl.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AssetCriticalityRequestOptions } from '../../../../../common/api/search_strategy/asset_criticality/all'; +import { createQueryFilterClauses } from '../../../../utils/build_query'; + +export const buildAssetCriticalityQuery = ({ + timerange, + filterQuery, + defaultIndex, + pagination: { querySize, cursorStart } = { + querySize: QUERY_SIZE, + cursorStart: 0, + }, +}: AssetCriticalityRequestOptions) => { + const filter = createQueryFilterClauses(filterQuery); + + if (timerange) { + filter.push({ + range: { + '@timestamp': { + gte: timerange.from, + lte: timerange.to, + format: 'strict_date_optional_time', + }, + }, + }); + } + + const dslQuery = { + index: defaultIndex, + allow_no_indices: false, + ignore_unavailable: true, + track_total_hits: true, + size: querySize, + from: cursorStart, + body: { + query: { bool: { filter } }, + }, + }; + + return dslQuery; +}; + +export const QUERY_SIZE = 10; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts index 1e04b6910601c..ad60ec516cb53 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts @@ -9,6 +9,9 @@ import { getOr } from 'lodash/fp'; import type { IEsSearchResponse } from '@kbn/search-types'; import type { IScopedClusterClient } from '@kbn/core/server'; +import type { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import _ from 'lodash'; +import type { AssetCriticalityRecord } from '../../../../../../common/api/entity_analytics'; import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants'; import type { HostAggEsItem, @@ -32,6 +35,8 @@ import { formatHostEdgesData, HOSTS_FIELDS } from './helpers'; import type { EndpointAppContext } from '../../../../../endpoint/types'; import { buildRiskScoreQuery } from '../../risk_score/all/query.risk_score.dsl'; +import { buildAssetCriticalityQuery } from '../../asset_criticality/query.asset_criticality.dsl'; +import { getAssetCriticalityIndex } from '../../../../../../common/entity_analytics/asset_criticality'; export const allHosts: SecuritySolutionFactory = { buildDsl: (options) => { @@ -97,29 +102,23 @@ async function enhanceEdges( esClient: IScopedClusterClient, isNewRiskScoreModuleInstalled: boolean ): Promise { - const hostRiskData = await getHostRiskData( - esClient, - spaceId, - hostNames, - isNewRiskScoreModuleInstalled - ); - const hostsRiskByHostName: Record | undefined = hostRiskData?.hits.hits.reduce( - (acc, hit) => ({ - ...acc, - [hit._source?.host.name ?? '']: hit._source?.host?.risk?.calculated_level, - }), - {} - ); + const [riskByHostName, criticalityByHostName] = await Promise.all([ + getHostRiskData(esClient, spaceId, hostNames, isNewRiskScoreModuleInstalled).then( + buildRecordFromAggs('host.name', 'host.risk.calculated_level') + ), + getHostCriticalityData(esClient, hostNames).then( + buildRecordFromAggs('id_value', 'criticality_level') + ), + ]); - return hostsRiskByHostName - ? edges.map(({ node, cursor }) => ({ - node: { - ...node, - risk: hostsRiskByHostName[node._id ?? ''], - }, - cursor, - })) - : edges; + return edges.map(({ node, cursor }) => ({ + node: { + ...node, + risk: riskByHostName?.[node._id ?? ''], + criticality: criticalityByHostName?.[node._id ?? ''], + }, + cursor, + })); } export async function getHostRiskData( @@ -145,3 +144,33 @@ export async function getHostRiskData( return undefined; } } + +export async function getHostCriticalityData(esClient: IScopedClusterClient, hostNames: string[]) { + try { + const criticalityResponse = await esClient.asCurrentUser.search( + buildAssetCriticalityQuery({ + defaultIndex: [getAssetCriticalityIndex('default')], // TODO:(@tiansivive) move to constant or import from somewhere else + filterQuery: { terms: { id_value: hostNames } }, + }) + ); + return criticalityResponse; + } catch (error) { + if (error?.meta?.body?.error?.type !== 'index_not_found_exception') { + throw error; + } + return undefined; + } +} + +const buildRecordFromAggs = + (key: string, path: string) => + ( + data: SearchResponse> | undefined + ): Record | undefined => + data?.hits.hits.reduce( + (acc, hit) => ({ + ...acc, + [_.get(hit._source, key) || '']: _.get(hit._source, path), + }), + {} + ); From cc72854dcda09cbafc13ef0d0b51fcbe4d7f93f9 Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Wed, 19 Jun 2024 14:14:38 +0200 Subject: [PATCH 111/127] [Dataset quality] Synthtrace script for load testing Dataset Quality (#184804) This commit adds the synthtrace scenario `logs_traces_hosts` script . It's designed to generate synthetic log, trace, and host data (interlinked via `service.name`, `host.name` and other fields) for testing and development purposes. The script generates data based on a set of predefined scenarios and parameters and prefers to use atomic names over sequentially generated names. For more details, see https://github.com/elastic/kibana/pull/184804. --- .../src/lib/infra/host.ts | 1 + .../src/lib/logs/index.ts | 4 + .../src/scenarios/logs_traces_hosts.ts | 467 ++++++++++++++++++ 3 files changed, 472 insertions(+) create mode 100644 packages/kbn-apm-synthtrace/src/scenarios/logs_traces_hosts.ts diff --git a/packages/kbn-apm-synthtrace-client/src/lib/infra/host.ts b/packages/kbn-apm-synthtrace-client/src/lib/infra/host.ts index 136b3cf227a9d..b4425156e6780 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/infra/host.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/infra/host.ts @@ -16,6 +16,7 @@ interface HostDocument extends Fields { 'host.name': string; 'metricset.name'?: string; 'event.module'?: string; + 'service.name'?: string; } class Host extends Entity { diff --git a/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts b/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts index a649d60df57a2..489221eea3d7a 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts @@ -25,11 +25,14 @@ export type LogDocument = Fields & 'host.name'?: string; 'container.id'?: string; 'trace.id'?: string; + 'transaction.id'?: string; 'agent.id'?: string; 'agent.name'?: string; 'orchestrator.cluster.name'?: string; 'orchestrator.cluster.id'?: string; 'orchestrator.resource.id'?: string; + 'kubernetes.pod.uid'?: string; + 'aws.s3.bucket.name'?: string; 'orchestrator.namespace'?: string; 'container.name'?: string; 'cloud.provider'?: string; @@ -40,6 +43,7 @@ export type LogDocument = Fields & 'error.stack_trace'?: string; 'error.exception.stacktrace'?: string; 'error.log.stacktrace'?: string; + 'log.custom': Record; }>; class Log extends Serializable { diff --git a/packages/kbn-apm-synthtrace/src/scenarios/logs_traces_hosts.ts b/packages/kbn-apm-synthtrace/src/scenarios/logs_traces_hosts.ts new file mode 100644 index 0000000000000..a745ef6d2bca2 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/logs_traces_hosts.ts @@ -0,0 +1,467 @@ +/* + * Copyright 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 { + log, + LogDocument, + InfraDocument, + apm, + Instance, + infra, + ApmFields, + generateShortId, +} from '@kbn/apm-synthtrace-client'; +import { Scenario } from '../cli/scenario'; +import { Logger } from '../lib/utils/create_logger'; +import { withClient } from '../lib/utils/with_client'; +import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; + +const ENVIRONMENT = getSynthtraceEnvironment(__filename); + +// Use e.g. # ... --scenarioOpts.numServices=5 --scenarioOpts.customFieldPrefix="metric". See https://github.com/elastic/kibana/pull/184804 for more details. +const DEFAULT_SCENARIO_OPTS = { + numSpaces: 1, + numServices: 10, + numHosts: 10, + numAgents: 5, + numDatasets: 6, // Won't be used if `datasets` option is provided + datasets: undefined, // Provide a list of datasets --scenarioOpts.datasets="apache.access" --scenarioOpts.datasets="nginx.error" to override the default list + degradedRatio: 0.25, // Percentage of logs that are malformed (over limit or mapping conflict) + numCustomFields: 50, // Number of custom field (e.g. `log.custom.field-1: "abc"`) per document + customFieldPrefix: 'field', // Prefix for custom fields (e.g. `log.custom.field-1: "abc"`) + logsInterval: '1m', + logsRate: 1, + ingestHosts: true, + ingestTraces: true, +}; + +const scenario: Scenario = async (runOptions) => { + return { + generate: ({ range, clients: { logsEsClient, infraEsClient, apmEsClient } }) => { + const { + numSpaces, + numServices, + numHosts, + numAgents, + numDatasets, + datasets, + degradedRatio, + numCustomFields, + customFieldPrefix, + logsInterval, + logsRate, + ingestHosts, + ingestTraces, + } = { ...DEFAULT_SCENARIO_OPTS, ...(runOptions.scenarioOpts || {}) }; + const { logger } = runOptions; + + killIfUnknownScenarioOptions(logger, runOptions.scenarioOpts || {}); + + // Infra Hosts + const infraHosts = Array(numHosts) + .fill(0) + .map((_, idx) => infra.host(getRotatedItem(idx, HOSTS, numHosts))); + + const hosts = range + .interval('1m') + .rate(1) + .generator((timestamp) => { + const agent = getRotatedItem(timestamp, AGENTS, numAgents); + const service = getRotatedItem(timestamp, SERVICE_NAMES, numServices); + + return infraHosts.flatMap((host) => + [ + host.cpu().timestamp(timestamp), + host.memory().timestamp(timestamp), + host.network().timestamp(timestamp), + host.load().timestamp(timestamp), + host.filesystem().timestamp(timestamp), + host.diskio().timestamp(timestamp), + ].map((metric) => + metric.defaults({ + 'host.name': host.fields['host.name'], + 'host.hostname': host.fields['host.name'], + 'agent.id': agent.id, + 'service.name': service, + 'system.memory.actual.free': 500 + Math.floor(Math.random() * 500), + 'system.memory.total': 1000, + 'system.cpu.total.norm.pct': 0.5 + Math.random() * 0.25, + }) + ) + ); + }); + + // APM Traces + const instances = [...Array(numServices).keys()].map((index) => { + const agent = getRotatedItem(index, AGENTS, numAgents); + + return apm + .service({ + name: getRotatedItem(index, SERVICE_NAMES, numServices), + environment: ENVIRONMENT, + agentName: agent.name, + }) + .instance(getRotatedItem(index, HOSTS, numHosts)); + }); + const instanceSpans = (instance: Instance) => { + const successfulTraceEvents = range + .interval('1m') + .rate(1) + .generator((timestamp) => { + const isError = Math.random() < 0.5; + const cloudRegion = getRotatedItem(timestamp, CLOUD_REGION, 3); + const agent = getRotatedItem(timestamp, AGENTS, numAgents); + + const transaction = instance + .transaction({ transactionName: getRotatedItem(timestamp, TRANSACTION_NAMES, 3) }) + .timestamp(timestamp) + .duration(1000) + .defaults({ + 'trace.id': `trace-id-${getTimestampBlock(timestamp, 3 * 60 * 1000)}`, + 'transaction.id': `transaction-id-${getTimestampBlock(timestamp, 2 * 60 * 1000)}`, + 'span.id': `span-id-${getTimestampBlock(timestamp, 60 * 1000)}`, + 'agent.name': agent.name, + 'cloud.region': cloudRegion, + 'cloud.provider': getRotatedItem(timestamp, CLOUD_PROVIDERS, 3), + 'cloud.project.id': generateShortId(), + 'cloud.availability_zone': `${cloudRegion}a`, + 'service.name': getRotatedItem(timestamp, SERVICE_NAMES, numServices), + 'service.environment': ENVIRONMENT, + }); + + if (isError) { + transaction.failure().errors( + instance + .error({ + message: '[ResponseError] index_not_found_exception', + type: 'ResponseError', + }) + .timestamp(timestamp) + ); + } else { + transaction.success().children( + instance + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) + .duration(1000) + .success() + .destination('elasticsearch') + .timestamp(timestamp), + instance + .span({ spanName: 'custom_operation', spanType: 'custom' }) + .duration(100) + .success() + .timestamp(timestamp) + ); + } + + return transaction; + }); + + return [successfulTraceEvents]; + }; + + // Logs + const logDatasets = datasets ? (Array.isArray(datasets) ? datasets : [datasets]) : DATASETS; + const numLogDatasets = datasets ? logDatasets.length : numDatasets; + const cloudProjectId = `cloud-project-${generateShortId()}`; + const logs = range + .interval(logsInterval) + .rate(logsRate) + .generator((timestamp, index) => { + const isMalformed = index > 0 && Math.random() < degradedRatio; // `index > 0` to wait for dynamic templates + const cloudRegion = getRotatedItem(timestamp, CLOUD_REGION, 3); + const dataset = getRotatedItem(timestamp, logDatasets, numLogDatasets); + const space = getRotatedItem(timestamp, NAMESPACES, numSpaces); + const hostName = getRotatedItem(timestamp, HOSTS, numHosts); + const agent = getRotatedItem(timestamp, AGENTS, numAgents); + const service = getRotatedItem(timestamp, SERVICE_NAMES, numServices); + const logLevel = getRotatedItem(timestamp, LOG_LEVELS, LOG_LEVELS.length); + const message = `Log message for logs-${dataset}-${space}. logLevel: ${logLevel}. isMalformed: ${isMalformed}. dataset: ${dataset}. space: ${space}. cloudRegion: ${cloudRegion}.`; + const customFields = getExtraFields(numCustomFields, isMalformed, customFieldPrefix); + + return log + .create() + .dataset(dataset) + .message(message) + .logLevel(logLevel) + .namespace(space) + .hostName(hostName) + .service(service) + .containerId(`container.${Math.random() > 0.5 ? 1 : 2}.${hostName}`) + .defaults({ + 'trace.id': `trace-id-${getTimestampBlock(timestamp, 3 * 60 * 1000)}`, + 'transaction.id': `transaction-id-${getTimestampBlock(timestamp, 2 * 60 * 1000)}`, + 'agent.id': agent.id, + 'agent.name': agent.name, + 'container.id': generateShortId(), + 'orchestrator.cluster.name': getRotatedItem(timestamp, CLUSTERS, 3).clusterName, + 'orchestrator.cluster.id': getRotatedItem(timestamp, CLUSTERS, 3).clusterId, + 'orchestrator.resource.id': generateShortId(), + 'kubernetes.pod.uid': `kb.${Math.random() > 0.5 ? 1 : 2}.${hostName}`, + 'aws.s3.bucket.name': `aws.bk.${Math.random() > 0.5 ? 1 : 2}.${hostName}`, + 'cloud.provider': getRotatedItem(timestamp, CLOUD_PROVIDERS, 3), + 'cloud.region': cloudRegion, + 'cloud.availability_zone': `${cloudRegion}a`, + 'cloud.project.id': cloudProjectId, + 'cloud.instance.id': getRotatedItem(timestamp, CLUSTERS, 3).clusterId, + 'log.file.path': `/logs/${generateShortId()}/${logLevel}.txt`, + 'log.custom': customFields, + }) + .timestamp(timestamp); + }); + + return [ + ...(ingestHosts + ? [ + withClient( + infraEsClient, + logger.perf('generating_infra_hosts', () => hosts) + ), + ] + : []), + ...(ingestTraces + ? [ + withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances.flatMap((instance) => instanceSpans(instance)) + ) + ), + ] + : []), + withClient( + logsEsClient, + logger.perf('generating_logs', () => logs) + ), + ]; + }, + }; +}; + +export default scenario; + +/** + * The function will pick an item from the list of items and rotate the item based on the index and maxPickCount. + * + * @param index Current running index of the item. Can be any sequential number. + * @param items List of items to pick from. + * @param maxPickCount How many items to pick from the list. If maxPickCount > items.length, then it will pick all items. + */ +function getRotatedItem(index: number, items: T[], maxPickCount: number) { + const normalizedIndex = Math.floor(index > 1000000 ? index / 1000 : index); // To randomize timestamps + const maxLength = Math.min(maxPickCount, items.length); + return items[normalizedIndex % maxLength]; +} + +/** + * The function will return the (passed) timestamp block based on the milliInterval. + * + * @param timestamp The timestamp to get the block for. + * @param milliInterval The interval in milliseconds. E.g. 30000 for 30 second block. + */ +function getTimestampBlock(timestamp: number, milliInterval: number) { + const remainder = timestamp % milliInterval; + return timestamp - remainder; +} + +/** + * Generate extra fields with sequential keys (0 - n) to simulate extra/custom log fields in a log document. + * + * @param numFields Number of fields to generate. + * @param isDegraded If true, will generate fields with more than 1024 characters, and will use a mix of numeric and + * string values to cause mapping conflicts. If false, will generate first half with numeric values and second half with + * string values. + * @param customFieldPrefix Prefix for the field key. Default is 'field'. + */ +function getExtraFields( + numFields: number, + isDegraded = false, + customFieldPrefix = DEFAULT_SCENARIO_OPTS.customFieldPrefix +) { + const extraFields: Record = {}; + for (let i = 0; i < numFields; i++) { + if (isDegraded) { + extraFields[`${customFieldPrefix}-${i}`] = getRandomSlice( + MORE_THAN_1024_CHARS, + MORE_THAN_1024_CHARS.length + ); + } else { + if (i % 2 === 0) { + extraFields[`${customFieldPrefix}-${i}`] = Math.random() * 1000 * 1000; // Assign half of the fields with numeric values + } else { + extraFields[`${customFieldPrefix}-${i}`] = getRandomSlice(MORE_THAN_1024_CHARS, 200); + } + } + } + return extraFields; +} + +/** + * Slices a string from the start index to a random number until length. + */ +function getRandomSlice(str: string, maxLength: number, startIndex = 0) { + const start = Math.min(str.length, startIndex); + const end = Math.min(str.length, start + Math.floor(Math.random() * maxLength)); + return str.slice(start, end); +} + +function killIfUnknownScenarioOptions(logger: Logger, options: Record) { + const unknownOptions = Object.keys(options).filter( + (key) => !Object.keys(DEFAULT_SCENARIO_OPTS).includes(key) + ); + if (unknownOptions.length > 0) { + logger.error(`Unknown scenario option(s): ${unknownOptions.join(', ')}`); + process.exit(1); + } +} + +const NAMESPACES = ['default', 'space-01', 'space-02', 'space-03']; + +const SERVICE_NAMES = [ + 'frontend-rum', + 'azure-functions', + 'frontend', + 'checkout-service', + 'synth-go', + 'synth-node', + 'synth-dotnet', + 'synth-java', + 'productcatalogservice', + 'synth-rum', + 'auditbeat', + 'synth-node-0', + 'payment-service', + 'opbeans-java-otel', + 'packetbeat', + 'cartservice', + 'web-go-0', + 'aws-lambdas', + 'opbeans-go', + 'synth-service-0', + 'synth-service-1', + 'order-processing-dotnet-1', + 'synth-java-0', + 'arn:aws:lambda:us-west-2:001:function:fn-node-2', + 'opbeans-ruby', + 'synth-android', + 'currencyservice', + 'opbeans-python', + 'synth-ios', + 'shippingservice', + 'adservice', + 'recommendationservice', + 'frauddetectionservice', + 'paymentservice', + 'checkoutservice', + 'emailservice', + 'quoteservice', +]; + +const HOSTS = [ + 'apache-integrations-557cfb8fcb-6kb65', + 'mysql-integrations-6b69cc89b4-fzhvw', + 'docker-integrations-6cf69b8966-mnccd', + 'siem-linux-edge-lite-oblt', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-wrzm', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-vvnh', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-tc5h', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-rc92', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-mlgl', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-l7r5', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-js5d', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-f4q6', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-ddlj', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-d18l', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-9m5v', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-7jvw', + 'gke-edge-lite-oblt-edge-lite-oblt-poo-0d6e31aa-475z', +]; + +const CLUSTERS = [ + { clusterId: generateShortId(), clusterName: 'synth-cluster-1' }, + { clusterId: generateShortId(), clusterName: 'synth-cluster-2' }, + { clusterId: generateShortId(), clusterName: 'synth-cluster-3' }, +]; +const CLOUD_PROVIDERS = ['gcp', 'aws', 'azure']; +const CLOUD_REGION = ['eu-central-1', 'us-east-1', 'area-51']; +const AGENTS = [ + { id: 'go-id', name: 'go' }, + { id: 'rum-js-id', name: 'rum-js' }, + { id: 'nodejs-id', name: 'nodejs' }, + { id: 'opbeans-java-id', name: 'opbeans-java' }, + { id: 'opbeans-node-id', name: 'opbeans-node' }, + { id: 'opbeans-python-id', name: 'opbeans-python' }, + { id: 'opbeans-ruby-id', name: 'opbeans-ruby' }, + { id: 'opbeans-dotnet-id', name: 'opbeans-dotnet' }, + { id: 'synth-agent-id', name: 'synth-agent' }, +]; + +const TRANSACTION_NAMES = ['GET /synth/customers', 'GET /synth/orders', 'GET /synth/articles']; + +const DATASETS = [ + 'apache.access', + 'apache.error', + 'nginx.access', + 'nginx.error', + 'apm.access', + 'apm.error', + 'apm.metrics', + 'mysql.access', + 'mysql.error', + 'kubernetes.audit_logs', + 'kubernetes.container_logs', + 'system.syslog', + 'postgresql.error', + 'postgresql.log', + 'redis.error', + 'redis.log', + 'mongodb.error', + 'mongodb.log', + 'activemq.audit', + 'activemq.log', + 'elasticsearch.audit', + 'elasticsearch.slowlog', + 'akamai.siem', + 'auditd.log', + 'auditd_manager.auditd', + 'cloud_security_posture.findings', + 'docker.container_logs', + 'elastic_agent.apm_server', + 'elastic_agent.filebeat', + 'elastic_agent.heartbeat', + 'fleet_server.output_health', + 'fleet_server.logs', + 'kibana.audit', + 'kibana.log', + 'microsoft_sqlserver.audit', + 'microsoft_sqlserver.log', + 'network_traffic.http', + 'network_traffic.dns', + 'apm.logs', + 'apm.traces', + 'apm.rum', + 'apm.profiling', + 'apm.uptime', + 'apm.synthetics', + 'apm.infra', + 'apm.sourcemap', + 'apm.span', + 'apm.transaction', + 'synth.1', + 'synth.2', + 'synth.3', +]; + +const LOG_LEVELS = ['info', 'error', 'warn', 'debug']; + +const MORE_THAN_1024_CHARS = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?'; From 328187b4f86b237056d60e5452b0f6830069dd76 Mon Sep 17 00:00:00 2001 From: Vadim Kibana <82822460+vadimkibana@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:17:24 +0200 Subject: [PATCH 112/127] [ES|QL] AST and `Walker` support for ES|QL params (#186410) ## Summary Closes https://github.com/elastic/kibana/issues/186305 Adds support for (1) un-named, (2) named, and (3) positional ES|QL parameters. ``` ROW unnamed = ?, named = ?named, positional = ?1 ``` - Adds AST node generation. - Adds `Walker`, with support to walk through the parameters. - `Walker.params(ast)` collects all params into an array. #### AST node interface The AST nodes follow the existing "literal" type pattern, which has `type` and `literalTypes` fields. Un-named param `?` AST nodes: ```ts { type: 'literal', literalType: 'param', paramType: 'unnamed', } ``` Named param `?name` AST nodes: ```ts { type: 'literal', literalType: 'param', paramType: 'named', value: 'name', } ``` Positional param `?123` AST nodes: ```ts { type: 'literal', literalType: 'param', paramType: 'positional', value: 123, } ``` ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-esql-ast/index.ts | 2 + .../src/__tests__/ast_parser.params.test.ts | 176 ++++++++++++++++++ packages/kbn-esql-ast/src/ast_helpers.ts | 2 + packages/kbn-esql-ast/src/ast_walker.ts | 57 ++++++ packages/kbn-esql-ast/src/types.ts | 40 +++- packages/kbn-esql-ast/src/walker/index.ts | 9 + .../kbn-esql-ast/src/walker/walker.test.ts | 69 +++++++ packages/kbn-esql-ast/src/walker/walker.ts | 128 +++++++++++++ .../src/definitions/functions.ts | 4 +- .../src/definitions/options.ts | 2 +- .../src/validation/validation.ts | 2 +- 11 files changed, 486 insertions(+), 5 deletions(-) create mode 100644 packages/kbn-esql-ast/src/__tests__/ast_parser.params.test.ts create mode 100644 packages/kbn-esql-ast/src/walker/index.ts create mode 100644 packages/kbn-esql-ast/src/walker/walker.test.ts create mode 100644 packages/kbn-esql-ast/src/walker/walker.ts diff --git a/packages/kbn-esql-ast/index.ts b/packages/kbn-esql-ast/index.ts index 4f93614ffa487..c418110ccab87 100644 --- a/packages/kbn-esql-ast/index.ts +++ b/packages/kbn-esql-ast/index.ts @@ -37,3 +37,5 @@ export { getParser, getLexer, ROOT_STATEMENT } from './src/antlr_facade'; export { getAstAndSyntaxErrors } from './src/ast_parser'; export { ESQLErrorListener } from './src/antlr_error_listener'; + +export { Walker, type WalkerOptions, walk } from './src/walker'; diff --git a/packages/kbn-esql-ast/src/__tests__/ast_parser.params.test.ts b/packages/kbn-esql-ast/src/__tests__/ast_parser.params.test.ts new file mode 100644 index 0000000000000..f69412a053e02 --- /dev/null +++ b/packages/kbn-esql-ast/src/__tests__/ast_parser.params.test.ts @@ -0,0 +1,176 @@ +/* + * Copyright 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 { getAstAndSyntaxErrors as parse } from '../ast_parser'; +import { Walker } from '../walker'; + +/** + * Un-named parameters are represented by a question mark "?". + */ +describe('un-named parameters', () => { + describe('correctly formatted', () => { + it('can parse a single un-named param', () => { + const query = 'ROW x = ?'; + const { ast, errors } = parse(query); + const params = Walker.params(ast); + + expect(errors.length).toBe(0); + expect(params).toMatchObject([ + { + type: 'literal', + literalType: 'param', + paramType: 'unnamed', + location: { + min: 8, + max: 8, + }, + }, + ]); + + const { min, max } = params[0].location; + + expect(query.slice(min, max + 1)).toBe('?'); + }); + }); +}); + +/** + * Positional parameters are represented by a question mark followed by a number "?1". + */ +describe('positional parameters', () => { + describe('correctly formatted', () => { + it('can parse a single positional param', () => { + const query = 'ROW x = ?1'; + const { ast, errors } = parse(query); + const params = Walker.params(ast); + + expect(errors.length).toBe(0); + expect(params).toMatchObject([ + { + type: 'literal', + literalType: 'param', + paramType: 'positional', + value: 1, + location: { + min: 8, + max: 9, + }, + }, + ]); + + const { min, max } = params[0].location; + + expect(query.slice(min, max + 1)).toBe('?1'); + }); + + it('multiple positional params', () => { + const query = 'ROW x = ?5, x2 = ?5, y = ?6, z = ?7'; + const { ast, errors } = parse(query); + const params = Walker.params(ast); + + expect(errors.length).toBe(0); + expect(params.length).toBe(4); + params.sort((a, b) => a.location.min - b.location.min); + expect(params).toMatchObject([ + { + type: 'literal', + literalType: 'param', + paramType: 'positional', + value: 5, + }, + { + type: 'literal', + literalType: 'param', + paramType: 'positional', + value: 5, + }, + { + type: 'literal', + literalType: 'param', + paramType: 'positional', + value: 6, + }, + { + type: 'literal', + literalType: 'param', + paramType: 'positional', + value: 7, + }, + ]); + }); + }); +}); + +/** + * Named parameters are represented by a question mark followed by a name "?name". + */ +describe('named parameters', () => { + describe('correctly formatted', () => { + it('can parse a single named param', () => { + const query = 'ROW x = ?theName'; + const { ast, errors } = parse(query); + const params = Walker.params(ast); + + expect(errors.length).toBe(0); + expect(params).toMatchObject([ + { + type: 'literal', + literalType: 'param', + paramType: 'named', + value: 'theName', + location: { + min: 8, + max: 15, + }, + }, + ]); + + const { min, max } = params[0].location; + + expect(query.slice(min, max + 1)).toBe('?theName'); + }); + }); + + it('multiple named params', () => { + const query = 'ROW x = ?a, y = ?b, z = ?c'; + const { ast, errors } = parse(query); + const params = Walker.params(ast); + + expect(errors.length).toBe(0); + expect(params.length).toBe(3); + params.sort((a, b) => a.location.min - b.location.min); + expect(params).toMatchObject([ + { + type: 'literal', + literalType: 'param', + paramType: 'named', + value: 'a', + }, + { + type: 'literal', + literalType: 'param', + paramType: 'named', + value: 'b', + }, + { + type: 'literal', + literalType: 'param', + paramType: 'named', + value: 'c', + }, + ]); + }); + + describe('when incorrectly formatted, returns errors', () => { + it('two question marks "?" in a row', () => { + const text = 'ROW x = ??'; + const { errors } = parse(text); + expect(errors.length > 0).toBe(true); + }); + }); +}); diff --git a/packages/kbn-esql-ast/src/ast_helpers.ts b/packages/kbn-esql-ast/src/ast_helpers.ts index 69ea76c091146..76e130f233807 100644 --- a/packages/kbn-esql-ast/src/ast_helpers.ts +++ b/packages/kbn-esql-ast/src/ast_helpers.ts @@ -163,6 +163,8 @@ export function createLiteral( literalType: type, value: Number(text), }; + } else if (type === 'param') { + throw new Error('Should never happen'); } return { ...partialLiteral, diff --git a/packages/kbn-esql-ast/src/ast_walker.ts b/packages/kbn-esql-ast/src/ast_walker.ts index fc47227a0b0ed..8584f65bac2b1 100644 --- a/packages/kbn-esql-ast/src/ast_walker.ts +++ b/packages/kbn-esql-ast/src/ast_walker.ts @@ -15,6 +15,7 @@ import { BooleanDefaultContext, type BooleanExpressionContext, BooleanLiteralContext, + InputParamsContext, BooleanValueContext, type CommandOptionsContext, ComparisonContext, @@ -58,6 +59,8 @@ import { ValueExpressionDefaultContext, IndexIdentifierContext, InlineCastContext, + InputNamedOrPositionalParamContext, + InputParamContext, } from './antlr/esql_parser'; import { createSource, @@ -88,6 +91,9 @@ import type { ESQLCommandOption, ESQLAstItem, ESQLInlineCast, + ESQLUnnamedParamLiteral, + ESQLPositionalParamLiteral, + ESQLNamedParamLiteral, } from './types'; export function collectAllSourceIdentifiers(ctx: FromCommandContext): ESQLAstItem[] { @@ -338,6 +344,57 @@ function getConstant(ctx: ConstantContext): ESQLAstItem { } return createList(ctx, values); } + if (ctx instanceof InputParamsContext && ctx.children) { + const values: ESQLLiteral[] = []; + + for (const child of ctx.children) { + if (child instanceof InputParamContext) { + const literal: ESQLUnnamedParamLiteral = { + type: 'literal', + literalType: 'param', + paramType: 'unnamed', + text: ctx.getText(), + name: '', + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; + values.push(literal); + } else if (child instanceof InputNamedOrPositionalParamContext) { + const text = child.getText(); + const value = text.slice(1); + const valueAsNumber = Number(value); + const isPositional = String(valueAsNumber) === value; + + if (isPositional) { + const literal: ESQLPositionalParamLiteral = { + type: 'literal', + literalType: 'param', + paramType: 'positional', + value: valueAsNumber, + text, + name: '', + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; + values.push(literal); + } else { + const literal: ESQLNamedParamLiteral = { + type: 'literal', + literalType: 'param', + paramType: 'named', + value, + text, + name: '', + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; + values.push(literal); + } + } + } + + return values; + } return createUnknownItem(ctx); } diff --git a/packages/kbn-esql-ast/src/types.ts b/packages/kbn-esql-ast/src/types.ts index 22a53d6368d9d..ebea0aeeb89f0 100644 --- a/packages/kbn-esql-ast/src/types.ts +++ b/packages/kbn-esql-ast/src/types.ts @@ -10,6 +10,8 @@ export type ESQLAst = ESQLAstCommand[]; export type ESQLAstCommand = ESQLCommand | ESQLAstMetricsCommand; +export type ESQLAstNode = ESQLAstCommand | ESQLAstItem; + export type ESQLSingleAstItem = | ESQLFunction | ESQLCommandOption @@ -22,6 +24,8 @@ export type ESQLSingleAstItem = | ESQLInlineCast | ESQLUnknownItem; +export type ESQLAstField = ESQLFunction | ESQLColumn; + export type ESQLAstItem = ESQLSingleAstItem | ESQLAstItem[]; export interface ESQLLocation { @@ -107,7 +111,8 @@ export type ESQLLiteral = | ESQLNumberLiteral | ESQLBooleanLiteral | ESQLNullLiteral - | ESQLStringLiteral; + | ESQLStringLiteral + | ESQLParamLiteral; // @internal export interface ESQLNumberLiteral extends ESQLAstBaseItem { @@ -137,6 +142,39 @@ export interface ESQLStringLiteral extends ESQLAstBaseItem { value: string; } +// @internal +export interface ESQLParamLiteral extends ESQLAstBaseItem { + type: 'literal'; + literalType: 'param'; + paramType: ParamType; + value?: string | number; +} + +/** + * *Unnamed* parameter is not named, just a question mark "?". + * + * @internal + */ +export type ESQLUnnamedParamLiteral = ESQLParamLiteral<'unnamed'>; + +/** + * *Named* parameter is a question mark followed by a name "?name". + * + * @internal + */ +export interface ESQLNamedParamLiteral extends ESQLParamLiteral<'named'> { + value: string; +} + +/** + * *Positional* parameter is a question mark followed by a number "?1". + * + * @internal + */ +export interface ESQLPositionalParamLiteral extends ESQLParamLiteral<'positional'> { + value: number; +} + export interface ESQLMessage { type: 'error' | 'warning'; text: string; diff --git a/packages/kbn-esql-ast/src/walker/index.ts b/packages/kbn-esql-ast/src/walker/index.ts new file mode 100644 index 0000000000000..5dea00bed0f8a --- /dev/null +++ b/packages/kbn-esql-ast/src/walker/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 { Walker, type WalkerOptions, walk } from './walker'; diff --git a/packages/kbn-esql-ast/src/walker/walker.test.ts b/packages/kbn-esql-ast/src/walker/walker.test.ts new file mode 100644 index 0000000000000..11c8a141080d5 --- /dev/null +++ b/packages/kbn-esql-ast/src/walker/walker.test.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. + */ + +import { ESQLColumn, ESQLLiteral, getAstAndSyntaxErrors } from '../..'; +import { walk, Walker } from './walker'; + +test('can walk all functions', () => { + const { ast } = getAstAndSyntaxErrors('METRICS index a(b(c(foo)))'); + const functions: string[] = []; + + walk(ast, { + visitFunction: (fn) => functions.push(fn.name), + }); + + expect(functions.sort()).toStrictEqual(['a', 'b', 'c']); +}); + +test('can walk "columns"', () => { + const query = 'ROW x = 1'; + const { ast } = getAstAndSyntaxErrors(query); + const columns: ESQLColumn[] = []; + + walk(ast, { + visitColumn: (node) => columns.push(node), + }); + + expect(columns).toMatchObject([ + { + type: 'column', + name: 'x', + }, + ]); +}); + +test('can walk literals', () => { + const query = 'ROW x = 1'; + const { ast } = getAstAndSyntaxErrors(query); + const columns: ESQLLiteral[] = []; + + walk(ast, { + visitLiteral: (node) => columns.push(node), + }); + + expect(columns).toMatchObject([ + { + type: 'literal', + name: '1', + }, + ]); +}); + +test('can collect all params', () => { + const query = 'ROW x = ?'; + const { ast } = getAstAndSyntaxErrors(query); + const params = Walker.params(ast); + + expect(params).toMatchObject([ + { + type: 'literal', + literalType: 'param', + paramType: 'unnamed', + }, + ]); +}); diff --git a/packages/kbn-esql-ast/src/walker/walker.ts b/packages/kbn-esql-ast/src/walker/walker.ts new file mode 100644 index 0000000000000..8ebf6911599d4 --- /dev/null +++ b/packages/kbn-esql-ast/src/walker/walker.ts @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { + ESQLAstCommand, + ESQLAstItem, + ESQLAstNode, + ESQLColumn, + ESQLFunction, + ESQLLiteral, + ESQLParamLiteral, + ESQLSingleAstItem, +} from '../types'; + +export interface WalkerOptions { + visitSingleAstItem?: (node: ESQLSingleAstItem) => void; + visitFunction?: (node: ESQLFunction) => void; + visitColumn?: (node: ESQLColumn) => void; + visitLiteral?: (node: ESQLLiteral) => void; +} + +export class Walker { + /** + * Walks the AST and calls the appropriate visitor functions. + */ + public static readonly walk = ( + node: ESQLAstNode | ESQLAstNode[], + options: WalkerOptions + ): Walker => { + const walker = new Walker(options); + walker.walk(node); + return walker; + }; + + /** + * Walks the AST and extracts all parameter literals. + * + * @param node AST node to extract parameters from. + */ + public static readonly params = (node: ESQLAstNode | ESQLAstNode[]): ESQLParamLiteral[] => { + const params: ESQLParamLiteral[] = []; + Walker.walk(node, { + visitLiteral: (param) => { + if (param.literalType === 'param') { + params.push(param); + } + }, + }); + return params; + }; + + constructor(protected readonly options: WalkerOptions) {} + + public walk(node: undefined | ESQLAstNode | ESQLAstNode[]): void { + if (!node) return; + + if (node instanceof Array) { + for (const item of node) this.walk(item); + return; + } + + switch (node.type) { + case 'command': { + this.walkCommand(node as ESQLAstCommand); + break; + } + default: { + this.walkAstItem(node as ESQLAstItem); + break; + } + } + } + + public walkCommand(node: ESQLAstCommand): void { + switch (node.name) { + default: { + this.walk(node.args); + break; + } + } + } + + public walkAstItem(node: ESQLAstItem): void { + if (node instanceof Array) { + const list = node as ESQLAstItem[]; + for (const item of list) this.walkAstItem(item); + } else { + const item = node as ESQLSingleAstItem; + this.walkSingleAstItem(item); + } + } + + public walkSingleAstItem(node: ESQLSingleAstItem): void { + const { options } = this; + options.visitSingleAstItem?.(node); + switch (node.type) { + case 'function': { + this.walkFunction(node as ESQLFunction); + break; + } + case 'column': { + options.visitColumn?.(node); + break; + } + case 'literal': { + options.visitLiteral?.(node); + break; + } + } + } + + public walkFunction(node: ESQLFunction): void { + this.options.visitFunction?.(node); + const args = node.args; + const length = args.length; + for (let i = 0; i < length; i++) { + const arg = args[i]; + this.walkAstItem(arg); + } + } +} + +export const walk = Walker.walk; diff --git a/packages/kbn-esql-validation-autocomplete/src/definitions/functions.ts b/packages/kbn-esql-validation-autocomplete/src/definitions/functions.ts index 77f4195f15a82..6c96111b74d9e 100644 --- a/packages/kbn-esql-validation-autocomplete/src/definitions/functions.ts +++ b/packages/kbn-esql-validation-autocomplete/src/definitions/functions.ts @@ -1345,7 +1345,7 @@ const logDefinition: FunctionDefinition = { // do not really care here about the base and field // just need to check both values are not negative for (const arg of fnDef.args) { - if (isLiteralItem(arg) && arg.value < 0) { + if (isLiteralItem(arg) && Number(arg.value) < 0) { messages.push({ type: 'warning' as const, code: 'logOfNegativeValue', @@ -1398,7 +1398,7 @@ const log10Definition: FunctionDefinition = { // do not really care here about the base and field // just need to check both values are not negative for (const arg of fnDef.args) { - if (isLiteralItem(arg) && arg.value < 0) { + if (isLiteralItem(arg) && Number(arg.value) < 0) { messages.push({ type: 'warning' as const, code: 'logOfNegativeValue', diff --git a/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts b/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts index 13e3ea66ef106..cd81ae3096e54 100644 --- a/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts +++ b/packages/kbn-esql-validation-autocomplete/src/definitions/options.ts @@ -135,7 +135,7 @@ export const appendSeparatorOption: CommandOptionsDefinition = { messages.push( getMessageFromId({ messageId: 'wrongDissectOptionArgumentType', - values: { value }, + values: { value: value ?? '' }, locations: firstArg.location, }) ); diff --git a/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts b/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts index 438d1fd826d00..a0c2d385c3e99 100644 --- a/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts +++ b/packages/kbn-esql-validation-autocomplete/src/validation/validation.ts @@ -109,7 +109,7 @@ function validateFunctionLiteralArg( values: { name: astFunction.name, argType: argDef.type, - value: actualArg.value, + value: typeof actualArg.value === 'number' ? actualArg.value : String(actualArg.value), givenType: actualArg.literalType, }, locations: actualArg.location, From c0b65d605ce03847336f393912688a8998b9cb6e Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Wed, 19 Jun 2024 09:04:48 -0400 Subject: [PATCH 113/127] feat(slo): group by instance id (#186131) --- .../src/rest_specs/routes/find_group.ts | 1 + .../kbn-slo-schema/src/schema/common.ts | 1 + .../grouped_slos/group_list_view.tsx | 23 +----- .../grouped_slos/group_view.test.tsx | 56 +++++++++++++- .../grouped_slos/hooks/use_group_name.test.ts | 76 +++++++++++++++++++ .../grouped_slos/hooks/use_group_name.ts | 67 ++++++++++++++++ .../slos/components/slo_list_group_by.tsx | 18 ++++- .../slo/server/services/find_slo_groups.ts | 10 ++- 8 files changed, 225 insertions(+), 27 deletions(-) create mode 100644 x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts create mode 100644 x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find_group.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find_group.ts index 3c04134c83312..7c3f5e576cea5 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find_group.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/find_group.ts @@ -12,6 +12,7 @@ const groupBySchema = t.union([ t.literal('slo.tags'), t.literal('status'), t.literal('slo.indicator.type'), + t.literal('slo.instanceId'), t.literal('_index'), ]); diff --git a/x-pack/packages/kbn-slo-schema/src/schema/common.ts b/x-pack/packages/kbn-slo-schema/src/schema/common.ts index 188a5b8f07266..ff30ae5f25483 100644 --- a/x-pack/packages/kbn-slo-schema/src/schema/common.ts +++ b/x-pack/packages/kbn-slo-schema/src/schema/common.ts @@ -81,6 +81,7 @@ const groupSummarySchema = t.type({ id: t.string, instanceId: t.string, name: t.string, + groupings: t.record(t.string, t.unknown), }), }), violated: t.number, diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx index eefe5c1ba1e87..cee082338d78c 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_list_view.tsx @@ -27,12 +27,12 @@ import React, { memo, useState } from 'react'; import { paths } from '../../../../../common/locators/paths'; import { useFetchSloList } from '../../../../hooks/use_fetch_slo_list'; import { useKibana } from '../../../../utils/kibana_react'; -import { SLI_OPTIONS } from '../../../slo_edit/constants'; import { useSloFormattedSLIValue } from '../../hooks/use_slo_summary'; import type { SortDirection, SortField } from '../../hooks/use_url_search_state'; import { SlosView } from '../slos_view'; import { GroupByField } from '../slo_list_group_by'; import { SLOView } from '../toggle_slo_view'; +import { useGroupName } from './hooks/use_group_name'; interface Props { group: string; @@ -57,26 +57,7 @@ export function GroupListView({ }: Props) { const groupQuery = `"${groupBy}": "${group}"`; const query = kqlQuery ? `${groupQuery} and ${kqlQuery}` : groupQuery; - let groupName = group.toLowerCase(); - if (groupBy === 'slo.indicator.type') { - groupName = SLI_OPTIONS.find((option) => option.value === group)?.text ?? group; - } - if (groupBy === '_index') { - // get remote cluster name from index name - if (groupName.includes(':.')) { - const [remoteClusterName] = groupName.split(':.'); - groupName = i18n.translate('xpack.slo.group.remoteCluster', { - defaultMessage: 'Remote Cluster: {remoteClusterName}', - values: { - remoteClusterName, - }, - }); - } else { - groupName = i18n.translate('xpack.slo.group.remoteCluster.localKibana', { - defaultMessage: 'Local Kibana', - }); - } - } + const groupName = useGroupName(groupBy, group, summary); const [page, setPage] = useState(0); const [accordionState, setAccordionState] = useState<'open' | 'closed'>('closed'); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_view.test.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_view.test.tsx index 3c61534d479b7..775659f6be580 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_view.test.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/group_view.test.tsx @@ -105,17 +105,65 @@ describe('Group View', () => { { group: 'production', groupBy: 'slo.tags', - summary: { total: 3, worst: 0.95, healthy: 2, violated: 1, degrading: 0, noData: 0 }, + summary: { + total: 3, + worst: { + sliValue: 1, + status: 'healthy', + slo: { + id: 'irrelevant', + instanceId: 'irrelevant', + name: 'irrelevant', + groupings: {}, + }, + }, + healthy: 2, + violated: 1, + degrading: 0, + noData: 0, + }, }, { group: 'something', groupBy: 'slo.tags', - summary: { total: 1, worst: 0.9, healthy: 0, violated: 1, degrading: 0, noData: 0 }, + summary: { + total: 1, + worst: { + sliValue: 1, + status: 'healthy', + slo: { + id: 'irrelevant', + instanceId: 'irrelevant', + name: 'irrelevant', + groupings: {}, + }, + }, + healthy: 0, + violated: 1, + degrading: 0, + noData: 0, + }, }, { group: 'anything', groupBy: 'slo.tags', - summary: { total: 2, worst: 0.85, healthy: 1, violated: 0, degrading: 0, noData: 1 }, + summary: { + total: 2, + worst: { + sliValue: 1, + status: 'healthy', + slo: { + id: 'irrelevant', + instanceId: 'irrelevant', + name: 'irrelevant', + groupings: {}, + }, + }, + healthy: 1, + violated: 0, + degrading: 0, + noData: 1, + }, }, ], }, @@ -163,7 +211,7 @@ describe('Group View', () => { results: [ { group: 'production', - groupBy: 'tags', + groupBy: 'slo.tags', summary: { total: 3, worst: 0.95, healthy: 2, violated: 1, degrading: 0, noData: 0 }, }, ], diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts new file mode 100644 index 0000000000000..fa2b5192665ea --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../../../common/constants'; +import { GroupSummary } from '@kbn/slo-schema'; +import { useGroupName } from './use_group_name'; + +describe('useGroupName', () => { + it('returns the group name for ungrouped', () => { + const groupName = useGroupName('ungrouped', 'irrelevant', {} as GroupSummary); + expect(groupName).toBe('irrelevant'); + }); + + it('returns the group name for slo tags', () => { + const groupName = useGroupName('slo.tags', 'some-tag', {} as GroupSummary); + expect(groupName).toBe('some-tag'); + }); + + it('returns the group name for status', () => { + const groupName = useGroupName('status', 'HEALTHY', {} as GroupSummary); + expect(groupName).toBe('healthy'); + }); + + it('returns the group name for slo instanceId', () => { + const summary = { + total: 2, + violated: 0, + healthy: 2, + degrading: 0, + noData: 0, + worst: { + sliValue: 1, + status: 'healthy', + slo: { + id: 'slo-id', + name: 'slo-name', + instanceId: 'domain.com', + groupings: { + host: { + name: 'domain.com', + }, + }, + }, + }, + } as GroupSummary; + const groupName = useGroupName('slo.instanceId', 'domain.com', summary); + expect(groupName).toBe('host.name: domain.com'); + }); + + it('returns the group name for slo indicator type', () => { + const groupName = useGroupName('slo.indicator.type', 'sli.kql.custom', {} as GroupSummary); + expect(groupName).toBe('Custom Query'); + }); + + it('returns the group name for local index', () => { + const groupName = useGroupName( + '_index', + SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + {} as GroupSummary + ); + expect(groupName).toBe('Local Kibana'); + }); + + it('returns the group name for remote index', () => { + const groupName = useGroupName( + '_index', + `my-remote-cluster:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN}`, + {} as GroupSummary + ); + expect(groupName).toBe('Remote Cluster: my-remote-cluster'); + }); +}); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts new file mode 100644 index 0000000000000..ca6ddff88fb19 --- /dev/null +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { ALL_VALUE, GroupSummary } from '@kbn/slo-schema'; +import { assertNever } from '@kbn/std'; +import { SLI_OPTIONS } from '../../../../slo_edit/constants'; +import { GroupByField } from '../../slo_list_group_by'; + +export function useGroupName(groupBy: GroupByField, group: string, summary?: GroupSummary) { + const groupName = group.toLowerCase(); + + switch (groupBy) { + case 'ungrouped': + case 'slo.tags': + case 'status': + return groupName; + case 'slo.instanceId': + if (groupName === ALL_VALUE || !summary) { + return i18n.translate('xpack.slo.group.ungroupedInstanceId', { + defaultMessage: 'Ungrouped', + }); + } + + const groupNames = flattenObject(summary.worst.slo.groupings); + return Object.entries(groupNames) + .map(([key, value]) => `${key}: ${value}`) + .join(', '); + case 'slo.indicator.type': + return SLI_OPTIONS.find((option) => option.value === group)?.text ?? groupName; + case '_index': + if (groupName.includes(':.')) { + const [remoteClusterName] = groupName.split(':.'); + return i18n.translate('xpack.slo.group.remoteCluster', { + defaultMessage: 'Remote Cluster: {remoteClusterName}', + values: { + remoteClusterName, + }, + }); + } + + return i18n.translate('xpack.slo.group.remoteCluster.localKibana', { + defaultMessage: 'Local Kibana', + }); + + default: + assertNever(groupBy); + } +} + +function flattenObject(obj: Record, parentKey = '', result: Record = {}) { + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const newKey = parentKey ? `${parentKey}.${key}` : key; + if (typeof obj[key] === 'object' && obj[key] !== null) { + flattenObject(obj[key], newKey, result); + } else { + result[newKey] = obj[key]; + } + } + } + return result; +} diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_list_group_by.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_list_group_by.tsx index b2764a4b9ab19..d7175553fd178 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_list_group_by.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/slo_list_group_by.tsx @@ -13,7 +13,13 @@ import type { SearchState } from '../hooks/use_url_search_state'; import type { Option } from './slo_context_menu'; import { ContextMenuItem, SLOContextMenu } from './slo_context_menu'; -export type GroupByField = 'ungrouped' | 'slo.tags' | 'status' | 'slo.indicator.type' | '_index'; +export type GroupByField = + | 'ungrouped' + | 'slo.tags' + | 'status' + | 'slo.indicator.type' + | 'slo.instanceId' + | '_index'; export interface Props { onStateChange: (newState: Partial) => void; state: SearchState; @@ -80,6 +86,16 @@ export function SloGroupBy({ onStateChange, state, loading }: Props) { handleChangeGroupBy('slo.indicator.type'); }, }, + { + label: i18n.translate('xpack.slo.list.groupBy.sloInstanceId', { + defaultMessage: 'SLO instance id', + }), + checked: groupBy === 'slo.instanceId', + value: 'slo.instanceId', + onClick: () => { + handleChangeGroupBy('slo.instanceId'); + }, + }, ]; if (hasRemoteEnabled) { diff --git a/x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts b/x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts index c3fadc6f60ba0..7282f276ea572 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/find_slo_groups.ts @@ -87,7 +87,14 @@ export class FindSLOGroups { }, }, _source: { - includes: ['sliValue', 'status', 'slo.id', 'slo.instanceId', 'slo.name'], + includes: [ + 'sliValue', + 'status', + 'slo.id', + 'slo.instanceId', + 'slo.name', + 'slo.groupings', + ], }, size: 1, }, @@ -165,6 +172,7 @@ export class FindSLOGroups { id: sourceSummaryDoc.slo.id, instanceId: sourceSummaryDoc.slo.instanceId, name: sourceSummaryDoc.slo.name, + groupings: sourceSummaryDoc.slo.groupings, }, }, violated: bucket.violated?.doc_count, From 05723d4775347cc31cfbe4693bbb504fe25324b5 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Wed, 19 Jun 2024 15:31:44 +0200 Subject: [PATCH 114/127] [Discover][DocViewer] Convert EuiTable to EuiDataGrid. Enable up to 500 fields per page. (#175787) - Closes https://github.com/elastic/kibana/issues/174745 ## Summary This PR converts Doc Viewer table into EuiDataGrid to use its actions functionality. Screenshot 2024-05-17 at 20 18 44 Screenshot 2024-05-17 at 18 17 49 Screenshot 2024-05-17 at 18 18 05 Screenshot 2024-05-22 at 15 22 31 ## Testing Some cases to check while testing: - varios value formats - legacy table vs data grid - doc viewer flyout vs Single Document page ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Andrea Del Rio Co-authored-by: Davis McPhee Co-authored-by: Stratoula Kalafateli Co-authored-by: Davis McPhee --- packages/kbn-field-utils/index.ts | 4 - .../field_description_icon_button.test.tsx | 34 -- .../field_description_icon_button.tsx | 60 --- .../components/doc_viewer/doc_viewer_tab.tsx | 2 + .../__snapshots__/field_name.test.tsx.snap | 419 +++++++++------- .../src/components/field_name/field_name.scss | 12 +- .../src/components/field_name/field_name.tsx | 123 +++-- .../src/services/types.ts | 3 +- .../discover_internal_state_container.ts | 3 + .../discover_grid_flyout.test.tsx | 20 +- .../discover_grid_flyout.tsx | 257 ++-------- .../doc_table/components/table_row.test.tsx | 8 +- .../components/table_row_details.tsx | 2 +- .../context_awareness/__mocks__/index.ts | 2 +- .../public/context_awareness/types.ts | 2 +- src/plugins/discover/public/index.ts | 1 - .../esql_datagrid/public/data_grid.tsx | 2 +- .../esql_datagrid/public/row_viewer.test.tsx | 8 +- .../esql_datagrid/public/row_viewer.tsx | 207 +------- src/plugins/esql_datagrid/tsconfig.json | 3 +- .../doc_viewer_flyout/doc_viewer_flyout.tsx | 311 ++++++++++++ .../components/doc_viewer_flyout}/index.ts | 9 +- .../doc_viewer_source/get_height.test.tsx | 16 +- .../doc_viewer_source/get_height.tsx | 28 +- .../components/doc_viewer_source/source.tsx | 14 +- .../table_cell_actions.test.tsx.snap | 351 +++++++++++++ .../doc_viewer_table/legacy/table.tsx | 16 +- .../legacy/table_cell_actions.tsx | 14 +- .../components/doc_viewer_table/table.scss | 23 + .../components/doc_viewer_table/table.tsx | 434 +++++++++-------- .../table_cell_actions.test.tsx | 118 +++-- .../doc_viewer_table/table_cell_actions.tsx | 460 ++++++++++-------- .../public/components/index.ts | 1 + .../public/components/lazy_doc_viewer.tsx | 20 + .../components/lazy_doc_viewer_flyout.tsx | 17 + .../unified_doc_viewer/public/index.tsx | 11 +- .../unified_doc_viewer/public/plugin.tsx | 3 +- src/plugins/unified_doc_viewer/tsconfig.json | 4 +- test/accessibility/apps/discover.ts | 10 +- test/functional/apps/context/_filters.ts | 3 +- .../dashboard/group1/embeddable_data_grid.ts | 2 +- .../dashboard/group1/url_field_formatter.ts | 6 +- .../apps/discover/classic/_doc_table.ts | 6 +- .../apps/discover/classic/_esql_grid.ts | 4 +- .../group2_data_grid1/_data_grid_doc_table.ts | 6 +- .../_data_grid_field_tokens.ts | 2 +- .../apps/discover/group3/_doc_viewer.ts | 6 +- .../discover/group7/_runtime_fields_editor.ts | 2 +- test/functional/services/data_grid.ts | 29 +- .../translations/translations/fr-FR.json | 14 +- .../translations/translations/ja-JP.json | 14 +- .../translations/translations/zh-CN.json | 14 +- .../test_suites/common/context/_filters.ts | 3 +- .../discover/group2/_data_grid_doc_table.ts | 6 +- 54 files changed, 1849 insertions(+), 1300 deletions(-) delete mode 100644 packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.test.tsx delete mode 100644 packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.tsx create mode 100644 src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/doc_viewer_flyout.tsx rename {packages/kbn-field-utils/src/components/field_description_icon_button => src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout}/index.ts (65%) create mode 100644 src/plugins/unified_doc_viewer/public/components/doc_viewer_table/__snapshots__/table_cell_actions.test.tsx.snap create mode 100644 src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer.tsx create mode 100644 src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer_flyout.tsx diff --git a/packages/kbn-field-utils/index.ts b/packages/kbn-field-utils/index.ts index d631c51c757a4..3adb267938940 100644 --- a/packages/kbn-field-utils/index.ts +++ b/packages/kbn-field-utils/index.ts @@ -27,7 +27,3 @@ export { export { FieldIcon, type FieldIconProps, getFieldIconProps } from './src/components/field_icon'; export { FieldDescription, type FieldDescriptionProps } from './src/components/field_description'; -export { - FieldDescriptionIconButton, - type FieldDescriptionIconButtonProps, -} from './src/components/field_description_icon_button'; diff --git a/packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.test.tsx b/packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.test.tsx deleted file mode 100644 index c677415cd4ace..0000000000000 --- a/packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.test.tsx +++ /dev/null @@ -1,34 +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 { FieldDescriptionIconButton } from './field_description_icon_button'; -import { render, screen } from '@testing-library/react'; - -describe('FieldDescriptionIconButton', () => { - it('should render correctly when no custom description', async () => { - const { container } = render(); - expect(container).toBeEmptyDOMElement(); - }); - - it('should render correctly with a short custom description', async () => { - const customDescription = 'test this desc'; - render(); - expect(screen.queryByTestId('fieldDescription-bytes')).toBeNull(); - screen.queryByTestId('fieldDescriptionPopoverButton-bytes')?.click(); - expect(screen.queryByTestId('fieldDescription-bytes')).toHaveTextContent(customDescription); - }); - - it('should render correctly with a long custom description', async () => { - const customDescription = 'test this long desc '.repeat(8).trim(); - render(); - expect(screen.queryByTestId('fieldDescription-bytes')).toBeNull(); - screen.queryByTestId('fieldDescriptionPopoverButton-bytes')?.click(); - expect(screen.queryByTestId('fieldDescription-bytes')).toHaveTextContent(customDescription); - }); -}); diff --git a/packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.tsx b/packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.tsx deleted file mode 100644 index c0358c53cd27f..0000000000000 --- a/packages/kbn-field-utils/src/components/field_description_icon_button/field_description_icon_button.tsx +++ /dev/null @@ -1,60 +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 { css } from '@emotion/react'; -import { EuiButtonIcon, EuiPopover, EuiPopoverProps, useEuiTheme } from '@elastic/eui'; -import { FieldDescription, FieldDescriptionProps } from '../field_description'; - -export type FieldDescriptionIconButtonProps = Pick & { - field: FieldDescriptionProps['field']; -}; - -export const FieldDescriptionIconButton: React.FC = ({ - field, - ...otherProps -}) => { - const { euiTheme } = useEuiTheme(); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - - if (!field?.customDescription) { - return null; - } - - const buttonTitle = i18n.translate('fieldUtils.fieldDescriptionIconButtonTitle', { - defaultMessage: 'View field description', - }); - - return ( - - setIsPopoverOpen(false)} - panelProps={{ - css: css` - max-width: ${euiTheme.base * 20}px; - `, - }} - button={ - setIsPopoverOpen(!isPopoverOpen)} - /> - } - > - - - - ); -}; diff --git a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx index ad0f7d9461f58..95a4db9528ad2 100644 --- a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx @@ -46,6 +46,8 @@ export class DocViewerTab extends React.Component { !isEqual(nextProps.renderProps.hit.raw.highlight, this.props.renderProps.hit.raw.highlight) || nextProps.id !== this.props.id || !isEqual(nextProps.renderProps.columns, this.props.renderProps.columns) || + nextProps.renderProps.decreaseAvailableHeightBy !== + this.props.renderProps.decreaseAvailableHeightBy || nextState.hasError ); } diff --git a/packages/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap b/packages/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap index c63b1b5bc0d11..cf9ddb38bbe69 100644 --- a/packages/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap +++ b/packages/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap @@ -1,268 +1,349 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`FieldName renders a custom description icon 1`] = ` -Array [ +
- - - String - - -
, -
- - - test + + + String + - +
+
+
- -
+ - -
-
+ + test + + +
-
, -] +
+
`; exports[`FieldName renders a geo field 1`] = ` -Array [ +
- - - Geo point - - -
, + + + Geo point + + +
+ +
- - - test.test.test + + + test.test.test + - +
- , -] + + `; exports[`FieldName renders a number field by providing a field record 1`] = ` -Array [ +
- - - Number - - -
, + + + Number + + +
+ +
- - - test.test.test + + + test.test.test + - +
- , -] + + `; exports[`FieldName renders a string field by providing fieldType and fieldName 1`] = ` -Array [ +
- - - String - - -
, + + + String + + +
+ +
- - - test + + + test + - +
- , -] + + `; exports[`FieldName renders unknown field 1`] = ` -Array [ +
- - - Unknown field - - -
, + + + Unknown field + + +
+ +
- - - test.test.test + + + test.test.test + - +
- , -] + + `; exports[`FieldName renders when mapping is provided 1`] = ` -Array [ +
- - - Number - - -
, + + + Number + + +
+ +
- - - bytes + + + bytes + - +
- , -] + + `; exports[`FieldName renders with a search highlight 1`] = ` -Array [ +
- - - Number - - -
, + + + Number + + +
+ +
- - - - te - - st.test.test + + + + te + + st.test.test + - +
- , -] + + `; diff --git a/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.scss b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.scss index edc4ea270d755..fce22a86b8c73 100644 --- a/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.scss +++ b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.scss @@ -1,12 +1,20 @@ -.kbnDocViewer__fieldIcon { +.kbnDocViewer__fieldIconContainer { padding-top: $euiSizeXS * 1.5; + line-height: $euiSize; } .kbnDocViewer__fieldName { - line-height: $euiLineHeight; padding: $euiSizeXS; + padding-left: 0; + line-height: $euiLineHeight; + + .euiDataGridRowCell__popover & { + font-size: $euiFontSizeS; + line-height: $euiLineHeight; + } } .kbnDocViewer__multiFieldBadge { @include euiFont; + margin: $euiSizeXS 0; } diff --git a/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx index 9494cc4d03ae0..d7f380195947a 100644 --- a/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx @@ -6,15 +6,22 @@ * Side Public License, v 1. */ -import React, { Fragment } from 'react'; +import React from 'react'; import './field_name.scss'; -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiHighlight } from '@elastic/eui'; +import { + EuiBadge, + EuiFlexGroup, + EuiFlexItem, + EuiToolTip, + EuiHighlight, + EuiIcon, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { FieldIcon, FieldIconProps } from '@kbn/react-field'; import type { DataViewField } from '@kbn/data-views-plugin/public'; import { getDataViewFieldSubtypeMulti } from '@kbn/es-query'; -import { FieldDescriptionIconButton, getFieldTypeName } from '@kbn/field-utils'; +import { getFieldTypeName } from '@kbn/field-utils'; interface Props { fieldName: string; @@ -23,6 +30,7 @@ interface Props { fieldIconProps?: Omit; scripted?: boolean; highlight?: string; + isPinned?: boolean; } export function FieldName({ @@ -32,6 +40,7 @@ export function FieldName({ fieldIconProps, scripted = false, highlight = '', + isPinned = false, }: Props) { const typeName = getFieldTypeName(fieldType); const displayName = @@ -41,54 +50,76 @@ export function FieldName({ const isMultiField = !!subTypeMulti?.multi; return ( - - - + + + + + + + {isPinned && ( + + + + )} + - - - + + - {displayName} - - - - {fieldMapping?.customDescription ? ( - - + + {displayName} + - ) : null} - {isMultiField && ( - - - - - - )} - - + + + + + )} +
+ + ); } diff --git a/packages/kbn-unified-doc-viewer/src/services/types.ts b/packages/kbn-unified-doc-viewer/src/services/types.ts index 115583c738bb0..c6e10d09cea00 100644 --- a/packages/kbn-unified-doc-viewer/src/services/types.ts +++ b/packages/kbn-unified-doc-viewer/src/services/types.ts @@ -49,6 +49,7 @@ export interface DocViewRenderProps { onAddColumn?: (columnName: string) => void; onRemoveColumn?: (columnName: string) => void; docViewsRegistry?: DocViewsRegistry | ((prevRegistry: DocViewsRegistry) => DocViewsRegistry); + decreaseAvailableHeightBy?: number; } export type DocViewerComponent = React.FC; export type DocViewRenderFn = ( @@ -83,7 +84,7 @@ export interface FieldRecordLegacy { action: { isActive: boolean; onFilter?: DocViewFilterFn; - onToggleColumn: (field: string) => void; + onToggleColumn: ((field: string) => void) | undefined; flattenedField: unknown; }; field: { diff --git a/src/plugins/discover/public/application/main/state_management/discover_internal_state_container.ts b/src/plugins/discover/public/application/main/state_management/discover_internal_state_container.ts index 4b26822bf04a5..4ebbe94832d0c 100644 --- a/src/plugins/discover/public/application/main/state_management/discover_internal_state_container.ts +++ b/src/plugins/discover/public/application/main/state_management/discover_internal_state_container.ts @@ -73,6 +73,8 @@ export function getInternalStateContainer() { setDataView: (prevState: InternalState) => (nextDataView: DataView) => ({ ...prevState, dataView: nextDataView, + expandedDoc: + nextDataView?.id !== prevState.dataView?.id ? undefined : prevState.expandedDoc, }), setIsDataViewLoading: (prevState: InternalState) => (loading: boolean) => ({ ...prevState, @@ -130,6 +132,7 @@ export function getInternalStateContainer() { resetOnSavedSearchChange: (prevState: InternalState) => () => ({ ...prevState, overriddenVisContextAfterInvalidation: undefined, + expandedDoc: undefined, }), }, {}, diff --git a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx index 456f10d89dc89..2129610aad3a1 100644 --- a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx +++ b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx @@ -161,13 +161,13 @@ describe('Discover flyout', function () { it('displays document navigation when there is more than 1 doc available', async () => { const { component } = await mountComponent({ dataView: dataViewWithTimefieldMock }); - const docNav = findTestSubject(component, 'dscDocNavigation'); + const docNav = findTestSubject(component, 'docViewerFlyoutNavigation'); expect(docNav.length).toBeTruthy(); }); it('displays no document navigation when there are 0 docs available', async () => { const { component } = await mountComponent({ records: [], expandedHit: esHitsMock[0] }); - const docNav = findTestSubject(component, 'dscDocNavigation'); + const docNav = findTestSubject(component, 'docViewerFlyoutNavigation'); expect(docNav.length).toBeFalsy(); }); @@ -190,7 +190,7 @@ describe('Discover flyout', function () { }, ].map((hit) => buildDataTableRecord(hit, dataViewMock)); const { component } = await mountComponent({ records, expandedHit: esHitsMock[0] }); - const docNav = findTestSubject(component, 'dscDocNavigation'); + const docNav = findTestSubject(component, 'docViewerFlyoutNavigation'); expect(docNav.length).toBeFalsy(); }); @@ -230,19 +230,19 @@ describe('Discover flyout', function () { it('allows navigating with arrow keys through documents', async () => { const { component, props } = await mountComponent({}); - findTestSubject(component, 'docTableDetailsFlyout').simulate('keydown', { key: 'ArrowRight' }); + findTestSubject(component, 'docViewerFlyout').simulate('keydown', { key: 'ArrowRight' }); expect(props.setExpandedDoc).toHaveBeenCalledWith(expect.objectContaining({ id: 'i::2::' })); component.setProps({ ...props, hit: props.hits[1] }); - findTestSubject(component, 'docTableDetailsFlyout').simulate('keydown', { key: 'ArrowLeft' }); + findTestSubject(component, 'docViewerFlyout').simulate('keydown', { key: 'ArrowLeft' }); expect(props.setExpandedDoc).toHaveBeenCalledWith(expect.objectContaining({ id: 'i::1::' })); }); it('should not navigate with keypresses when already at the border of documents', async () => { const { component, props } = await mountComponent({}); - findTestSubject(component, 'docTableDetailsFlyout').simulate('keydown', { key: 'ArrowLeft' }); + findTestSubject(component, 'docViewerFlyout').simulate('keydown', { key: 'ArrowLeft' }); expect(props.setExpandedDoc).not.toHaveBeenCalled(); component.setProps({ ...props, hit: props.hits[props.hits.length - 1] }); - findTestSubject(component, 'docTableDetailsFlyout').simulate('keydown', { key: 'ArrowRight' }); + findTestSubject(component, 'docViewerFlyout').simulate('keydown', { key: 'ArrowRight' }); expect(props.setExpandedDoc).not.toHaveBeenCalled(); }); @@ -267,7 +267,7 @@ describe('Discover flyout', function () { }); const singleDocumentView = findTestSubject(component, 'docTableRowAction'); expect(singleDocumentView.length).toBeFalsy(); - const flyoutTitle = findTestSubject(component, 'docTableRowDetailsTitle'); + const flyoutTitle = findTestSubject(component, 'docViewerRowDetailsTitle'); expect(flyoutTitle.text()).toBe('Result'); }); @@ -279,7 +279,7 @@ describe('Discover flyout', function () { const { component } = await mountComponent({}); - const titleNode = findTestSubject(component, 'docTableRowDetailsTitle'); + const titleNode = findTestSubject(component, 'docViewerRowDetailsTitle'); expect(titleNode.text()).toBe(customTitle); }); @@ -503,7 +503,7 @@ describe('Discover flyout', function () { processRecord: (record) => services.profilesManager.resolveDocumentProfile({ record }), }); const { component } = await mountComponent({ records, services }); - const title = findTestSubject(component, 'docTableRowDetailsTitle'); + const title = findTestSubject(component, 'docViewerRowDetailsTitle'); expect(title.text()).toBe('Document #new::1::'); const content = findTestSubject(component, 'kbnDocViewer'); expect(content.text()).toBe('Mock tab'); diff --git a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx index 891ae384bd41a..778d05435e709 100644 --- a/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx +++ b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx @@ -6,40 +6,22 @@ * Side Public License, v 1. */ -import React, { useMemo, useCallback } from 'react'; -import { get } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { css } from '@emotion/react'; +import React, { useMemo } from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiFlyoutResizable, - EuiFlyoutBody, - EuiFlyoutFooter, - EuiFlyoutHeader, - EuiTitle, - EuiSpacer, - EuiPortal, - EuiPagination, - keys, - EuiButtonEmpty, - useEuiTheme, - useIsWithinMinBreakpoint, -} from '@elastic/eui'; import { Filter, Query, AggregateQuery, isOfAggregateQueryType } from '@kbn/es-query'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import type { DataTableColumnsMeta } from '@kbn/unified-data-table'; import type { DocViewsRegistry } from '@kbn/unified-doc-viewer'; -import { UnifiedDocViewer } from '@kbn/unified-doc-viewer-plugin/public'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { UnifiedDocViewerFlyout } from '@kbn/unified-doc-viewer-plugin/public'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import { useFlyoutActions } from './use_flyout_actions'; import { useDiscoverCustomization } from '../../customizations'; import { DiscoverGridFlyoutActions } from './discover_grid_flyout_actions'; import { useProfileAccessor } from '../../context_awareness'; +export const FLYOUT_WIDTH_KEY = 'discover:flyoutWidth'; + export interface DiscoverGridFlyoutProps { savedSearchId?: string; filters?: Filter[]; @@ -56,13 +38,6 @@ export interface DiscoverGridFlyoutProps { setExpandedDoc: (doc?: DataTableRecord) => void; } -function getIndexByDocId(hits: DataTableRecord[], id: string) { - return hits.findIndex((h) => { - return h.id === id; - }); -} - -export const FLYOUT_WIDTH_KEY = 'discover:flyoutWidth'; /** * Flyout displaying an expanded Elasticsearch document */ @@ -83,100 +58,26 @@ export function DiscoverGridFlyout({ }: DiscoverGridFlyoutProps) { const services = useDiscoverServices(); const flyoutCustomization = useDiscoverCustomization('flyout'); - const { euiTheme } = useEuiTheme(); - const isXlScreen = useIsWithinMinBreakpoint('xl'); - const DEFAULT_WIDTH = euiTheme.base * 34; - const defaultWidth = flyoutCustomization?.size ?? DEFAULT_WIDTH; // Give enough room to search bar to not wrap - const [flyoutWidth, setFlyoutWidth] = useLocalStorage(FLYOUT_WIDTH_KEY, defaultWidth); - const minWidth = euiTheme.base * 24; - const maxWidth = euiTheme.breakpoint.xl; - const isEsqlQuery = isOfAggregateQueryType(query); + const isESQLQuery = isOfAggregateQueryType(query); // Get actual hit with updated highlighted searches const actualHit = useMemo(() => hits?.find(({ id }) => id === hit?.id) || hit, [hit, hits]); - const pageCount = useMemo(() => (hits ? hits.length : 0), [hits]); - const activePage = useMemo(() => { - const id = hit.id; - if (!hits || pageCount <= 1) { - return -1; - } - - return getIndexByDocId(hits, id); - }, [hits, hit, pageCount]); - - const setPage = useCallback( - (index: number) => { - if (hits && hits[index]) { - setExpandedDoc(hits[index]); - } - }, - [hits, setExpandedDoc] - ); - - const onKeyDown = useCallback( - (ev: React.KeyboardEvent) => { - const nodeName = get(ev, 'target.nodeName', null); - if (typeof nodeName === 'string' && nodeName.toLowerCase() === 'input') { - return; - } - if (ev.key === keys.ARROW_LEFT || ev.key === keys.ARROW_RIGHT) { - ev.preventDefault(); - ev.stopPropagation(); - setPage(activePage + (ev.key === keys.ARROW_RIGHT ? 1 : -1)); - } - }, - [activePage, setPage] - ); const { flyoutActions } = useFlyoutActions({ actions: flyoutCustomization?.actions, dataView, - rowIndex: hit.raw._index, - rowId: hit.raw._id, + rowIndex: actualHit.raw._index, + rowId: actualHit.raw._id, columns, filters, savedSearchId, }); - const addColumn = useCallback( - (columnName: string) => { - onAddColumn(columnName); - services.toastNotifications.addSuccess( - i18n.translate('discover.grid.flyout.toastColumnAdded', { - defaultMessage: `Column ''{columnName}'' was added`, - values: { columnName }, - }) - ); - }, - [onAddColumn, services.toastNotifications] - ); - - const removeColumn = useCallback( - (columnName: string) => { - onRemoveColumn(columnName); - services.toastNotifications.addSuccess( - i18n.translate('discover.grid.flyout.toastColumnRemoved', { - defaultMessage: `Column ''{columnName}'' was removed`, - values: { columnName }, - }) - ); - }, - [onRemoveColumn, services.toastNotifications] - ); - - const defaultFlyoutTitle = isEsqlQuery - ? i18n.translate('discover.grid.tableRow.docViewerEsqlDetailHeading', { - defaultMessage: 'Result', - }) - : i18n.translate('discover.grid.tableRow.docViewerDetailHeading', { - defaultMessage: 'Document', - }); - const getDocViewerAccessor = useProfileAccessor('getDocViewer', { record: actualHit, }); const docViewer = useMemo(() => { const getDocViewer = getDocViewerAccessor(() => ({ - title: flyoutCustomization?.title ?? defaultFlyoutTitle, + title: flyoutCustomization?.title, docViewsRegistry: (registry: DocViewsRegistry) => typeof flyoutCustomization?.docViewsRegistry === 'function' ? flyoutCustomization.docViewsRegistry(registry) @@ -184,125 +85,33 @@ export function DiscoverGridFlyout({ })); return getDocViewer({ record: actualHit }); - }, [defaultFlyoutTitle, flyoutCustomization, getDocViewerAccessor, actualHit]); - - const renderDefaultContent = useCallback( - () => ( - - ), - [ - actualHit, - addColumn, - columns, - columnsMeta, - dataView, - hits, - isEsqlQuery, - onFilter, - removeColumn, - docViewer.docViewsRegistry, - ] - ); - - const contentActions = useMemo( - () => ({ - filter: onFilter, - onAddColumn: addColumn, - onRemoveColumn: removeColumn, - }), - [onFilter, addColumn, removeColumn] - ); - - const bodyContent = flyoutCustomization?.Content ? ( - - ) : ( - renderDefaultContent() - ); + }, [flyoutCustomization, getDocViewerAccessor, actualHit]); return ( - - - - - - -

{docViewer.title}

-
-
- {activePage !== -1 && ( - - - - )} -
- {isEsqlQuery || !flyoutActions.length ? null : ( - <> - - - - )} -
- {bodyContent} - - - {i18n.translate('discover.grid.flyout.close', { - defaultMessage: 'Close', - })} - - -
-
+ 0 ? ( + + ) : null + } + flyoutWidthLocalStorageKey={FLYOUT_WIDTH_KEY} + FlyoutCustomBody={flyoutCustomization?.Content} + services={services} + docViewsRegistry={docViewer.docViewsRegistry} + isEsqlQuery={isESQLQuery} + hit={hit} + hits={hits} + dataView={dataView} + columns={columns} + columnsMeta={columnsMeta} + onAddColumn={onAddColumn} + onRemoveColumn={onRemoveColumn} + onClose={onClose} + onFilter={onFilter} + setExpandedDoc={setExpandedDoc} + /> ); } diff --git a/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx b/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx index ad8b1c5a2f547..523d254b85311 100644 --- a/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx +++ b/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx @@ -113,16 +113,16 @@ describe('Doc table row component', () => { describe('details row', () => { it('should be empty by default', () => { const component = mountComponent(defaultProps); - expect(findTestSubject(component, 'docTableRowDetailsTitle').exists()).toBeFalsy(); + expect(findTestSubject(component, 'docViewerRowDetailsTitle').exists()).toBeFalsy(); }); it('should expand the detail row when the toggle arrow is clicked', () => { const component = mountComponent(defaultProps); const toggleButton = findTestSubject(component, 'docTableExpandToggleColumn'); - expect(findTestSubject(component, 'docTableRowDetailsTitle').exists()).toBeFalsy(); + expect(findTestSubject(component, 'docViewerRowDetailsTitle').exists()).toBeFalsy(); toggleButton.simulate('click'); - expect(findTestSubject(component, 'docTableRowDetailsTitle').exists()).toBeTruthy(); + expect(findTestSubject(component, 'docViewerRowDetailsTitle').exists()).toBeTruthy(); }); it('should hide the single/surrounding views for ES|QL mode', () => { @@ -133,7 +133,7 @@ describe('Doc table row component', () => { const component = mountComponent(props); const toggleButton = findTestSubject(component, 'docTableExpandToggleColumn'); toggleButton.simulate('click'); - expect(findTestSubject(component, 'docTableRowDetailsTitle').text()).toBe('Expanded result'); + expect(findTestSubject(component, 'docViewerRowDetailsTitle').text()).toBe('Expanded result'); expect(findTestSubject(component, 'docTableRowAction').length).toBeFalsy(); }); }); diff --git a/src/plugins/discover/public/components/doc_table/components/table_row_details.tsx b/src/plugins/discover/public/components/doc_table/components/table_row_details.tsx index 313b9e12090aa..03cee5ad78462 100644 --- a/src/plugins/discover/public/components/doc_table/components/table_row_details.tsx +++ b/src/plugins/discover/public/components/doc_table/components/table_row_details.tsx @@ -58,7 +58,7 @@ export const TableRowDetails = ({ - +

{isEsqlMode && ( { const recordId = params.record.id; const prevValue = prev(params); return { - title: `${prevValue.title} #${recordId}`, + title: `${prevValue.title ?? 'Document'} #${recordId}`, docViewsRegistry: (registry) => { registry.add({ id: 'doc_view_mock', diff --git a/src/plugins/discover/public/context_awareness/types.ts b/src/plugins/discover/public/context_awareness/types.ts index 4bc75e6e1727d..9dbec9fab8dae 100644 --- a/src/plugins/discover/public/context_awareness/types.ts +++ b/src/plugins/discover/public/context_awareness/types.ts @@ -11,7 +11,7 @@ import type { DocViewsRegistry } from '@kbn/unified-doc-viewer'; import type { DataTableRecord } from '@kbn/discover-utils'; export interface DocViewerExtension { - title: string; + title: string | undefined; docViewsRegistry: (prevRegistry: DocViewsRegistry) => DocViewsRegistry; } diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index bd88c4d6dbe09..b54356c8fd50b 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -24,7 +24,6 @@ export type { DiscoverCustomization, DiscoverCustomizationService, FlyoutCustomization, - FlyoutContentProps, SearchBarCustomization, UnifiedHistogramCustomization, TopNavCustomization, diff --git a/src/plugins/esql_datagrid/public/data_grid.tsx b/src/plugins/esql_datagrid/public/data_grid.tsx index c9e507295b9f3..f45f1ce7f9ead 100644 --- a/src/plugins/esql_datagrid/public/data_grid.tsx +++ b/src/plugins/esql_datagrid/public/data_grid.tsx @@ -62,7 +62,7 @@ const DataGrid: React.FC = (props) => { ) => ( { { const closeFlyoutSpy = jest.fn(); renderComponent(closeFlyoutSpy); await waitFor(() => { - userEvent.click(screen.getByTestId('esqlRowDetailsFlyoutCloseBtn')); + userEvent.click(screen.getByTestId('docViewerFlyoutCloseButton')); expect(closeFlyoutSpy).toHaveBeenCalled(); }); }); @@ -106,14 +106,14 @@ describe('RowViewer', () => { }, } as unknown as DataTableRecord); await waitFor(() => { - expect(screen.getByTestId('esqlTableRowNavigation')).toBeInTheDocument(); + expect(screen.getByTestId('docViewerFlyoutNavigation')).toBeInTheDocument(); }); }); it('doesnt display row navigation when there is only 1 row available', async () => { renderComponent(); await waitFor(() => { - expect(screen.queryByTestId('esqlTableRowNavigation')).not.toBeInTheDocument(); + expect(screen.queryByTestId('docViewerFlyoutNavigation')).not.toBeInTheDocument(); }); }); }); diff --git a/src/plugins/esql_datagrid/public/row_viewer.tsx b/src/plugins/esql_datagrid/public/row_viewer.tsx index 35c2b807fbbb3..d02c48b7c85e4 100644 --- a/src/plugins/esql_datagrid/public/row_viewer.tsx +++ b/src/plugins/esql_datagrid/public/row_viewer.tsx @@ -6,34 +6,15 @@ * Side Public License, v 1. */ -import React, { useMemo, useCallback } from 'react'; -import { get } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { css } from '@emotion/react'; +import React, { useMemo } from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiFlyoutResizable, - EuiFlyoutBody, - EuiFlyoutFooter, - EuiFlyoutHeader, - EuiTitle, - EuiPortal, - EuiPagination, - keys, - EuiButtonEmpty, - useEuiTheme, - useIsWithinMinBreakpoint, -} from '@elastic/eui'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import type { DataTableColumnsMeta } from '@kbn/unified-data-table'; -import { UnifiedDocViewer } from '@kbn/unified-doc-viewer-plugin/public'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { UnifiedDocViewerFlyout } from '@kbn/unified-doc-viewer-plugin/public'; import { NotificationsStart } from '@kbn/core-notifications-browser'; export interface RowViewerProps { - toastNotifications?: NotificationsStart; + notifications?: NotificationsStart; columns: string[]; columnsMeta?: DataTableColumnsMeta; hit: DataTableRecord; @@ -46,12 +27,6 @@ export interface RowViewerProps { setExpandedDoc: (doc?: DataTableRecord) => void; } -function getIndexByDocId(hits: DataTableRecord[], id: string) { - return hits.findIndex((h) => { - return h.id === id; - }); -} - export const FLYOUT_WIDTH_KEY = 'esqlTable:flyoutWidth'; /** * Flyout displaying an expanded ES|QL row @@ -62,172 +37,32 @@ export function RowViewer({ dataView, columns, columnsMeta, - toastNotifications, + notifications, flyoutType = 'push', onClose, onRemoveColumn, onAddColumn, setExpandedDoc, }: RowViewerProps) { - const { euiTheme } = useEuiTheme(); - - const isXlScreen = useIsWithinMinBreakpoint('xl'); - const DEFAULT_WIDTH = euiTheme.base * 34; - const defaultWidth = DEFAULT_WIDTH; - const [flyoutWidth, setFlyoutWidth] = useLocalStorage(FLYOUT_WIDTH_KEY, defaultWidth); - const minWidth = euiTheme.base * 24; - const maxWidth = euiTheme.breakpoint.xl; - - const actualHit = useMemo(() => hits?.find(({ id }) => id === hit?.id) || hit, [hit, hits]); - const pageCount = useMemo(() => (hits ? hits.length : 0), [hits]); - const activePage = useMemo(() => { - const id = hit.id; - if (!hits || pageCount <= 1) { - return -1; - } - - return getIndexByDocId(hits, id); - }, [hits, hit, pageCount]); - - const setPage = useCallback( - (index: number) => { - if (hits && hits[index]) { - setExpandedDoc(hits[index]); - } - }, - [hits, setExpandedDoc] - ); - - const onKeyDown = useCallback( - (ev: React.KeyboardEvent) => { - const nodeName = get(ev, 'target.nodeName', null); - if (typeof nodeName === 'string' && nodeName.toLowerCase() === 'input') { - return; - } - if (ev.key === keys.ARROW_LEFT || ev.key === keys.ARROW_RIGHT) { - ev.preventDefault(); - ev.stopPropagation(); - setPage(activePage + (ev.key === keys.ARROW_RIGHT ? 1 : -1)); - } - }, - [activePage, setPage] - ); - - const addColumn = useCallback( - (columnName: string) => { - onAddColumn(columnName); - toastNotifications?.toasts?.addSuccess?.( - i18n.translate('esqlDataGrid.grid.flyout.toastColumnAdded', { - defaultMessage: `Column '{columnName}' was added`, - values: { columnName }, - }) - ); - }, - [onAddColumn, toastNotifications] - ); - - const removeColumn = useCallback( - (columnName: string) => { - onRemoveColumn(columnName); - toastNotifications?.toasts?.addSuccess?.( - i18n.translate('esqlDataGrid.grid.flyout.toastColumnRemoved', { - defaultMessage: `Column '{columnName}' was removed`, - values: { columnName }, - }) - ); - }, - [onRemoveColumn, toastNotifications] - ); - - const renderDefaultContent = useCallback( - () => ( - - ), - [actualHit, addColumn, columns, columnsMeta, dataView, hits, removeColumn] - ); - - const bodyContent = renderDefaultContent(); + const services = useMemo(() => ({ toastNotifications: notifications?.toasts }), [notifications]); return ( - - - - - - -

- {i18n.translate('esqlDataGrid.grid.tableRow.docViewerEsqlDetailHeading', { - defaultMessage: 'Result', - })} -

-
-
- {activePage !== -1 && ( - - - - )} -
-
- {bodyContent} - - - {i18n.translate('esqlDataGrid.grid.flyout.close', { - defaultMessage: 'Close', - })} - - -
-
+ ); } diff --git a/src/plugins/esql_datagrid/tsconfig.json b/src/plugins/esql_datagrid/tsconfig.json index 5db30eb35fd20..1d8685bf55982 100644 --- a/src/plugins/esql_datagrid/tsconfig.json +++ b/src/plugins/esql_datagrid/tsconfig.json @@ -22,10 +22,9 @@ "@kbn/core", "@kbn/ui-actions-plugin", "@kbn/field-formats-plugin", - "@kbn/i18n", "@kbn/unified-doc-viewer-plugin", "@kbn/core-notifications-browser", - "@kbn/shared-ux-utility" + "@kbn/shared-ux-utility", ], "exclude": [ "target/**/*", diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/doc_viewer_flyout.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/doc_viewer_flyout.tsx new file mode 100644 index 0000000000000..640dbdeb4abfa --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/doc_viewer_flyout.tsx @@ -0,0 +1,311 @@ +/* + * Copyright 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, { useMemo, useCallback, type ComponentType } from 'react'; +import { get } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiFlyoutResizable, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiTitle, + EuiSpacer, + EuiPortal, + EuiPagination, + keys, + EuiButtonEmpty, + useEuiTheme, + useIsWithinMinBreakpoint, + EuiFlyoutProps, +} from '@elastic/eui'; +import type { DataTableRecord } from '@kbn/discover-utils/types'; +import type { DataTableColumnsMeta } from '@kbn/unified-data-table'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; +import type { ToastsStart } from '@kbn/core-notifications-browser'; +import type { DocViewFilterFn, DocViewRenderProps } from '@kbn/unified-doc-viewer/types'; +import { UnifiedDocViewer } from '../lazy_doc_viewer'; + +export interface UnifiedDocViewerFlyoutProps { + 'data-test-subj'?: string; + flyoutTitle?: string; + flyoutDefaultWidth?: EuiFlyoutProps['size']; + flyoutActions?: React.ReactNode; + flyoutType?: 'push' | 'overlay'; + flyoutWidthLocalStorageKey?: string; + FlyoutCustomBody?: ComponentType<{ + actions: Pick; + doc: DataTableRecord; + renderDefaultContent: () => React.ReactNode; + }>; + services: { + toastNotifications?: ToastsStart; + }; + docViewsRegistry?: DocViewRenderProps['docViewsRegistry']; + isEsqlQuery: boolean; + columns: string[]; + columnsMeta?: DataTableColumnsMeta; + hit: DataTableRecord; + hits?: DataTableRecord[]; + dataView: DataView; + onAddColumn: (column: string) => void; + onClose: () => void; + onFilter?: DocViewFilterFn; + onRemoveColumn: (column: string) => void; + setExpandedDoc: (doc?: DataTableRecord) => void; +} + +function getIndexByDocId(hits: DataTableRecord[], id: string) { + return hits.findIndex((h) => { + return h.id === id; + }); +} + +export const FLYOUT_WIDTH_KEY = 'unifiedDocViewer:flyoutWidth'; +/** + * Flyout displaying an expanded row details + */ +export function UnifiedDocViewerFlyout({ + 'data-test-subj': dataTestSubj, + flyoutTitle, + flyoutActions, + flyoutDefaultWidth, + flyoutType, + flyoutWidthLocalStorageKey, + FlyoutCustomBody, + services, + docViewsRegistry, + isEsqlQuery, + hit, + hits, + dataView, + columns, + columnsMeta, + onFilter, + onClose, + onRemoveColumn, + onAddColumn, + setExpandedDoc, +}: UnifiedDocViewerFlyoutProps) { + const { euiTheme } = useEuiTheme(); + const isXlScreen = useIsWithinMinBreakpoint('xl'); + const DEFAULT_WIDTH = euiTheme.base * 34; + const defaultWidth = flyoutDefaultWidth ?? DEFAULT_WIDTH; // Give enough room to search bar to not wrap + const [flyoutWidth, setFlyoutWidth] = useLocalStorage( + flyoutWidthLocalStorageKey ?? FLYOUT_WIDTH_KEY, + defaultWidth + ); + const minWidth = euiTheme.base * 24; + const maxWidth = euiTheme.breakpoint.xl; + // Get actual hit with updated highlighted searches + const actualHit = useMemo(() => hits?.find(({ id }) => id === hit?.id) || hit, [hit, hits]); + const pageCount = useMemo(() => (hits ? hits.length : 0), [hits]); + const activePage = useMemo(() => { + const id = hit.id; + if (!hits || pageCount <= 1) { + return -1; + } + + return getIndexByDocId(hits, id); + }, [hits, hit, pageCount]); + + const setPage = useCallback( + (index: number) => { + if (hits && hits[index]) { + setExpandedDoc(hits[index]); + } + }, + [hits, setExpandedDoc] + ); + + const onKeyDown = useCallback( + (ev: React.KeyboardEvent) => { + const nodeClasses = get(ev, 'target.className', ''); + if (typeof nodeClasses === 'string' && nodeClasses.includes('euiDataGrid')) { + // ignore events triggered from the data grid + return; + } + + const nodeName = get(ev, 'target.nodeName', null); + if (typeof nodeName === 'string' && nodeName.toLowerCase() === 'input') { + // ignore events triggered from the search input + return; + } + if (ev.key === keys.ARROW_LEFT || ev.key === keys.ARROW_RIGHT) { + ev.preventDefault(); + ev.stopPropagation(); + setPage(activePage + (ev.key === keys.ARROW_RIGHT ? 1 : -1)); + } + }, + [activePage, setPage] + ); + + const addColumn = useCallback( + (columnName: string) => { + onAddColumn(columnName); + services.toastNotifications?.addSuccess( + i18n.translate('unifiedDocViewer.flyout.toastColumnAdded', { + defaultMessage: `Column ''{columnName}'' was added`, + values: { columnName }, + }) + ); + }, + [onAddColumn, services.toastNotifications] + ); + + const removeColumn = useCallback( + (columnName: string) => { + onRemoveColumn(columnName); + services.toastNotifications?.addSuccess( + i18n.translate('unifiedDocViewer.flyout.toastColumnRemoved', { + defaultMessage: `Column ''{columnName}'' was removed`, + values: { columnName }, + }) + ); + }, + [onRemoveColumn, services.toastNotifications] + ); + + const renderDefaultContent = useCallback( + () => ( + + ), + [ + actualHit, + addColumn, + columns, + columnsMeta, + dataView, + hits, + isEsqlQuery, + onFilter, + removeColumn, + docViewsRegistry, + ] + ); + + const contentActions = useMemo( + () => ({ + filter: onFilter, + onAddColumn: addColumn, + onRemoveColumn: removeColumn, + }), + [onFilter, addColumn, removeColumn] + ); + + const bodyContent = FlyoutCustomBody ? ( + + ) : ( + renderDefaultContent() + ); + + const defaultFlyoutTitle = isEsqlQuery + ? i18n.translate('unifiedDocViewer.flyout.docViewerEsqlDetailHeading', { + defaultMessage: 'Result', + }) + : i18n.translate('unifiedDocViewer.flyout.docViewerDetailHeading', { + defaultMessage: 'Document', + }); + const currentFlyoutTitle = flyoutTitle ?? defaultFlyoutTitle; + + return ( + + + + + + +

{currentFlyoutTitle}

+
+
+ {activePage !== -1 && ( + + + + )} +
+ {isEsqlQuery || !flyoutActions ? null : ( + <> + + {flyoutActions} + + )} +
+ {bodyContent} + + + {i18n.translate('unifiedDocViewer.flyout.closeButtonLabel', { + defaultMessage: 'Close', + })} + + +
+
+ ); +} diff --git a/packages/kbn-field-utils/src/components/field_description_icon_button/index.ts b/src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/index.ts similarity index 65% rename from packages/kbn-field-utils/src/components/field_description_icon_button/index.ts rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/index.ts index 36ebc6ef3e114..81cb2f5cbb928 100644 --- a/packages/kbn-field-utils/src/components/field_description_icon_button/index.ts +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_flyout/index.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -export { - FieldDescriptionIconButton, - type FieldDescriptionIconButtonProps, -} from './field_description_icon_button'; +import { UnifiedDocViewerFlyout } from './doc_viewer_flyout'; + +// Required for usage in React.lazy +// eslint-disable-next-line import/no-default-export +export default UnifiedDocViewerFlyout; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx index e28df4d89d5bc..6c65b9ddf0bdb 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx @@ -7,8 +7,7 @@ */ import { monaco } from '@kbn/monaco'; -import { getHeight } from './get_height'; -import { MARGIN_BOTTOM } from './source'; +import { getHeight, DEFAULT_MARGIN_BOTTOM } from './get_height'; describe('getHeight', () => { Object.defineProperty(window, 'innerHeight', { writable: true, configurable: true, value: 500 }); @@ -32,28 +31,31 @@ describe('getHeight', () => { test('when using document explorer, returning the available height in the flyout', () => { const monacoMock = getMonacoMock(500, 0); - const height = getHeight(monacoMock, true); - expect(height).toBe(500 - MARGIN_BOTTOM); + const height = getHeight(monacoMock, true, DEFAULT_MARGIN_BOTTOM); + expect(height).toBe(484); + + const heightCustom = getHeight(monacoMock, true, 80); + expect(heightCustom).toBe(420); }); test('when using document explorer, returning the available height in the flyout has a minimun guarenteed height', () => { const monacoMock = getMonacoMock(500); - const height = getHeight(monacoMock, true); + const height = getHeight(monacoMock, true, DEFAULT_MARGIN_BOTTOM); expect(height).toBe(400); }); test('when using classic table, its displayed inline without scrolling', () => { const monacoMock = getMonacoMock(100); - const height = getHeight(monacoMock, false); + const height = getHeight(monacoMock, false, DEFAULT_MARGIN_BOTTOM); expect(height).toBe(1020); }); test('when using classic table, limited height > 500 lines to allow scrolling', () => { const monacoMock = getMonacoMock(1000); - const height = getHeight(monacoMock, false); + const height = getHeight(monacoMock, false, DEFAULT_MARGIN_BOTTOM); expect(height).toBe(5020); }); }); diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.tsx index dbab289018a63..5abade066cb95 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.tsx @@ -6,9 +6,29 @@ * Side Public License, v 1. */ import { monaco } from '@kbn/monaco'; -import { MARGIN_BOTTOM, MAX_LINES_CLASSIC_TABLE, MIN_HEIGHT } from './source'; +import { MAX_LINES_CLASSIC_TABLE, MIN_HEIGHT } from './source'; -export function getHeight(editor: monaco.editor.IStandaloneCodeEditor, useDocExplorer: boolean) { +// Displayed margin of the tab content to the window bottom +export const DEFAULT_MARGIN_BOTTOM = 16; + +export function getTabContentAvailableHeight( + elementRef: HTMLElement | undefined, + decreaseAvailableHeightBy: number +): number { + if (!elementRef) { + return 0; + } + + // assign a good height filling the available space of the document flyout + const position = elementRef.getBoundingClientRect(); + return window.innerHeight - position.top - decreaseAvailableHeightBy; +} + +export function getHeight( + editor: monaco.editor.IStandaloneCodeEditor, + useDocExplorer: boolean, + decreaseAvailableHeightBy: number +) { const editorElement = editor?.getDomNode(); if (!editorElement) { return 0; @@ -16,9 +36,7 @@ export function getHeight(editor: monaco.editor.IStandaloneCodeEditor, useDocExp let result; if (useDocExplorer) { - // assign a good height filling the available space of the document flyout - const position = editorElement.getBoundingClientRect(); - result = window.innerHeight - position.top - MARGIN_BOTTOM; + result = getTabContentAvailableHeight(editorElement, decreaseAvailableHeightBy); } else { // takes care of the classic table, display a maximum of 500 lines // why not display it all? Due to performance issues when the browser needs to render it all diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx index 430da5e15f1ad..bd88ec151189a 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx @@ -18,7 +18,7 @@ import { ElasticRequestState } from '@kbn/unified-doc-viewer'; import { isLegacyTableEnabled, SEARCH_FIELDS_FROM_SOURCE } from '@kbn/discover-utils'; import { getUnifiedDocViewerServices } from '../../plugin'; import { useEsDocSearch } from '../../hooks'; -import { getHeight } from './get_height'; +import { getHeight, DEFAULT_MARGIN_BOTTOM } from './get_height'; import { JSONCodeEditorCommonMemoized } from '../json_code_editor'; interface SourceViewerProps { @@ -28,6 +28,7 @@ interface SourceViewerProps { textBasedHits?: DataTableRecord[]; hasLineNumbers: boolean; width?: number; + decreaseAvailableHeightBy?: number; requestState?: ElasticRequestState; onRefresh: () => void; } @@ -35,8 +36,6 @@ interface SourceViewerProps { // Ihe number of lines displayed without scrolling used for classic table, which renders the component // inline limitation was necessary to enable virtualized scrolling, which improves performance export const MAX_LINES_CLASSIC_TABLE = 500; -// Displayed margin of the code editor to the window bottom when rendered in the document explorer flyout -export const MARGIN_BOTTOM = 80; // DocViewer flyout has a footer // Minimum height for the source content to guarantee minimum space when the flyout is scrollable. export const MIN_HEIGHT = 400; @@ -47,6 +46,7 @@ export const DocViewerSource = ({ width, hasLineNumbers, textBasedHits, + decreaseAvailableHeightBy, onRefresh, }: SourceViewerProps) => { const [editor, setEditor] = useState(); @@ -85,7 +85,11 @@ export const DocViewerSource = ({ return; } - const height = getHeight(editor, useDocExplorer); + const height = getHeight( + editor, + useDocExplorer, + decreaseAvailableHeightBy ?? DEFAULT_MARGIN_BOTTOM + ); if (height === 0) { return; } @@ -95,7 +99,7 @@ export const DocViewerSource = ({ } else { setEditorHeight(height); } - }, [editor, jsonValue, useDocExplorer, setEditorHeight]); + }, [editor, jsonValue, useDocExplorer, setEditorHeight, decreaseAvailableHeightBy]); const loadingState = (
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/__snapshots__/table_cell_actions.test.tsx.snap b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/__snapshots__/table_cell_actions.test.tsx.snap new file mode 100644 index 0000000000000..bbc8ee91569ad --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/__snapshots__/table_cell_actions.test.tsx.snap @@ -0,0 +1,351 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TableActions getFieldCellActions should render correctly for undefined functions 1`] = ` +Array [ + , + , +] +`; + +exports[`TableActions getFieldCellActions should render correctly for undefined functions 2`] = ` +Array [ + , +] +`; + +exports[`TableActions getFieldCellActions should render the panels correctly for defined onFilter function 1`] = ` +Array [ + , + , + , +] +`; + +exports[`TableActions getFieldValueCellActions should render correctly for undefined functions 1`] = `Array []`; + +exports[`TableActions getFieldValueCellActions should render the panels correctly for defined onFilter function 1`] = ` +Array [ + , + , +] +`; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx index deb5e5a52fb7a..0bdab73fe6c7f 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx @@ -37,19 +37,19 @@ export const DocViewerLegacyTable = ({ const tableColumns = useMemo(() => { return !hideActionsColumn ? [ACTIONS_COLUMN, ...MAIN_COLUMNS] : MAIN_COLUMNS; }, [hideActionsColumn]); - const onToggleColumn = useCallback( - (field: string) => { - if (!onRemoveColumn || !onAddColumn || !columns) { - return; - } + + const onToggleColumn = useMemo(() => { + if (!onRemoveColumn || !onAddColumn || !columns) { + return undefined; + } + return (field: string) => { if (columns.includes(field)) { onRemoveColumn(field); } else { onAddColumn(field); } - }, - [onRemoveColumn, onAddColumn, columns] - ); + }; + }, [onRemoveColumn, onAddColumn, columns]); const onSetRowProps = useCallback(({ field: { field } }: FieldRecordLegacy) => { return { diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx index 0b187c6d5b884..40d2265232294 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx @@ -20,7 +20,7 @@ interface TableActionsProps { flattenedField: unknown; fieldMapping?: DataViewField; onFilter: DocViewFilterFn; - onToggleColumn: (field: string) => void; + onToggleColumn: ((field: string) => void) | undefined; ignoredValue: boolean; } @@ -47,11 +47,13 @@ export const TableActions = ({ onClick={() => onFilter(fieldMapping, flattenedField, '-')} /> )} - onToggleColumn(field)} - /> + {onToggleColumn && ( + onToggleColumn(field)} + /> + )} {onFilter && ( ; - field: { - pinned: boolean; - onTogglePinned: (field: string) => void; - } & FieldRecordLegacy['field']; - value: FieldRecordLegacy['value']; -} +import { + type TableRow, + getFieldCellActions, + getFieldValueCellActions, + getFilterExistsDisabledWarning, + getFilterInOutPairDisabledWarning, +} from './table_cell_actions'; +import { + DEFAULT_MARGIN_BOTTOM, + getTabContentAvailableHeight, +} from '../doc_viewer_source/get_height'; + +export type FieldRecord = TableRow; interface ItemsEntry { pinnedItems: FieldRecord[]; restItems: FieldRecord[]; } -const MOBILE_OPTIONS = { header: false }; -const PAGE_SIZE_OPTIONS = [25, 50, 100]; +const MIN_NAME_COLUMN_WIDTH = 150; +const MAX_NAME_COLUMN_WIDTH = 350; +const PAGE_SIZE_OPTIONS = [25, 50, 100, 250, 500]; const DEFAULT_PAGE_SIZE = 25; const PINNED_FIELDS_KEY = 'discover:pinnedFields'; const PAGE_SIZE = 'discover:pageSize'; const SEARCH_TEXT = 'discover:searchText'; +const GRID_COLUMN_FIELD_NAME = 'name'; +const GRID_COLUMN_FIELD_VALUE = 'value'; + +const GRID_PROPS: Pick = { + columnVisibility: { + visibleColumns: ['name', 'value'], + setVisibleColumns: () => null, + }, + rowHeightsOptions: { defaultHeight: 'auto' }, + gridStyle: { + border: 'horizontal', + stripes: true, + rowHover: 'highlight', + header: 'underline', + cellPadding: 'm', + fontSize: 's', + }, +}; + const getPinnedFields = (dataViewId: string, storage: Storage): string[] => { const pinnedFieldsEntry = storage.get(PINNED_FIELDS_KEY); if ( @@ -114,18 +135,12 @@ export const DocViewerTable = ({ columnsMeta, hit, dataView, - hideActionsColumn, filter, + decreaseAvailableHeightBy, onAddColumn, onRemoveColumn, }: DocViewRenderProps) => { - const { euiTheme } = useEuiTheme(); - const [ref, setRef] = useState(null); - const dimensions = useResizeObserver(ref); - const showActionsInsideTableCell = dimensions?.width - ? dimensions.width > euiTheme.breakpoint.m - : false; - + const [containerRef, setContainerRef] = useState(null); const { fieldFormats, storage, uiSettings } = getUnifiedDocViewerServices(); const showMultiFields = uiSettings.get(SHOW_MULTIFIELDS); const currentDataViewId = dataView.id!; @@ -147,19 +162,18 @@ export const DocViewerTable = ({ const mapping = useCallback((name: string) => dataView.fields.getByName(name), [dataView.fields]); - const onToggleColumn = useCallback( - (field: string) => { - if (!onRemoveColumn || !onAddColumn || !columns) { - return; - } + const onToggleColumn = useMemo(() => { + if (!onRemoveColumn || !onAddColumn || !columns) { + return undefined; + } + return (field: string) => { if (columns.includes(field)) { onRemoveColumn(field); } else { onAddColumn(field); } - }, - [onRemoveColumn, onAddColumn, columns] - ); + }; + }, [onRemoveColumn, onAddColumn, columns]); const onTogglePinned = useCallback( (field: string) => { @@ -173,6 +187,15 @@ export const DocViewerTable = ({ [currentDataViewId, pinnedFields, storage] ); + const onSearch = useCallback( + (event: React.ChangeEvent) => { + const newSearchText = event.currentTarget.value; + updateSearchText(newSearchText, storage); + setSearchText(newSearchText); + }, + [storage] + ); + const fieldToItem = useCallback( (field: string, isPinned: boolean) => { const fieldMapping = mapping(field); @@ -193,7 +216,6 @@ export const DocViewerTable = ({ action: { onToggleColumn, onFilter: filter, - isActive: !!columns?.includes(field), flattenedField: flattened[field], }, field: { @@ -223,7 +245,6 @@ export const DocViewerTable = ({ hit, onToggleColumn, filter, - columns, columnsMeta, flattened, onTogglePinned, @@ -231,15 +252,6 @@ export const DocViewerTable = ({ ] ); - const handleOnChange = useCallback( - (event: React.ChangeEvent) => { - const newSearchText = event.currentTarget.value; - updateSearchText(newSearchText, storage); - setSearchText(newSearchText); - }, - [storage] - ); - const { pinnedItems, restItems } = Object.keys(flattened) .sort((fieldA, fieldB) => { const mappingA = mapping(fieldA); @@ -278,11 +290,12 @@ export const DocViewerTable = ({ } ); - const { curPageIndex, pageSize, totalPages, startIndex, changePageIndex, changePageSize } = - usePager({ - initialPageSize: getPageSize(storage), - totalItems: restItems.length, - }); + const rows = useMemo(() => [...pinnedItems, ...restItems], [pinnedItems, restItems]); + + const { curPageIndex, pageSize, totalPages, changePageIndex, changePageSize } = usePager({ + initialPageSize: getPageSize(storage), + totalItems: rows.length, + }); const showPagination = totalPages !== 0; const onChangePageSize = useCallback( @@ -293,126 +306,160 @@ export const DocViewerTable = ({ [changePageSize, storage] ); - const headers = [ - !hideActionsColumn && ( - - - - { + return showPagination + ? { + onChangeItemsPerPage: onChangePageSize, + onChangePage: changePageIndex, + pageIndex: curPageIndex, + pageSize, + pageSizeOptions: PAGE_SIZE_OPTIONS, + } + : undefined; + }, [showPagination, curPageIndex, pageSize, onChangePageSize, changePageIndex]); + + const fieldCellActions = useMemo( + () => getFieldCellActions({ rows, filter, onToggleColumn }), + [rows, filter, onToggleColumn] + ); + const fieldValueCellActions = useMemo( + () => getFieldValueCellActions({ rows, filter }), + [rows, filter] + ); + + useWindowSize(); // trigger re-render on window resize to recalculate the grid container height + const { width: containerWidth } = useResizeObserver(containerRef); + + const gridColumns: EuiDataGridProps['columns'] = useMemo( + () => [ + { + id: GRID_COLUMN_FIELD_NAME, + displayAsText: i18n.translate('unifiedDocViewer.fieldChooser.discoverField.name', { + defaultMessage: 'Field', + }), + initialWidth: Math.min( + Math.max(Math.round(containerWidth * 0.3), MIN_NAME_COLUMN_WIDTH), + MAX_NAME_COLUMN_WIDTH + ), + actions: false, + visibleCellActions: 3, + cellActions: fieldCellActions, + }, + { + id: GRID_COLUMN_FIELD_VALUE, + displayAsText: i18n.translate('unifiedDocViewer.fieldChooser.discoverField.value', { + defaultMessage: 'Value', + }), + actions: false, + visibleCellActions: 2, + cellActions: fieldValueCellActions, + }, + ], + [fieldCellActions, fieldValueCellActions, containerWidth] + ); + + const renderCellValue: EuiDataGridProps['renderCellValue'] = useCallback( + ({ rowIndex, columnId, isDetails }) => { + const row = rows[rowIndex]; + + if (!row) { + return null; + } + + const { + action: { flattenedField }, + field: { field, fieldMapping, fieldType, scripted, pinned }, + value: { formattedValue, ignored }, + } = row; + + if (columnId === 'name') { + return ( +
+ - - - - ), - - - - - - - , - - - - + +
+ ) : null} +
+ ); + } + + if (columnId === 'value') { + return ( + - - - , - ]; - - const renderRows = useCallback( - (items: FieldRecord[]) => { - return items.map( - ({ - action: { flattenedField, onFilter }, - field: { field, fieldMapping, fieldType, scripted, pinned }, - value: { formattedValue, ignored }, - }: FieldRecord) => { - return ( - - {!hideActionsColumn && ( - - - - )} - - - - - - - - ); - } + ); + } + + return null; + }, + [rows, searchText] + ); + + const renderCellPopover = useCallback( + (props: EuiDataGridCellPopoverElementProps) => { + const { columnId, children, cellActions, rowIndex } = props; + const row = rows[rowIndex]; + + let warningMessage: string | undefined; + if (columnId === GRID_COLUMN_FIELD_VALUE) { + warningMessage = getFilterInOutPairDisabledWarning(row); + } else if (columnId === GRID_COLUMN_FIELD_NAME) { + warningMessage = getFilterExistsDisabledWarning(row); + } + + return ( + <> + {children} + {cellActions} + {Boolean(warningMessage) && ( +
+ + +
+ )} + ); }, - [hideActionsColumn, showActionsInsideTableCell, onToggleColumn, onTogglePinned, searchText] + [rows] ); - const rowElements = [ - ...renderRows(pinnedItems), - ...renderRows(restItems.slice(startIndex, pageSize + startIndex)), - ]; + const containerHeight = containerRef + ? getTabContentAvailableHeight(containerRef, decreaseAvailableHeightBy ?? DEFAULT_MARGIN_BOTTOM) + : 0; return ( - + @@ -421,14 +468,14 @@ export const DocViewerTable = ({ - {rowElements.length === 0 ? ( + {rows.length === 0 ? (

) : ( - - - {headers} - {rowElements} - - - )} - - - - - - {showPagination && ( - - - + <> + + + + + + + )} ); diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx index 076ca2d67be10..86b6cb6acf833 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.test.tsx @@ -6,56 +6,82 @@ * Side Public License, v 1. */ import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { TableActions } from './table_cell_actions'; +import { getFieldCellActions, getFieldValueCellActions, TableRow } from './table_cell_actions'; import { DataViewField } from '@kbn/data-views-plugin/common'; describe('TableActions', () => { - it('should render the panels correctly for undefined onFilter function', () => { - render( - - ); - expect(screen.queryByTestId('addFilterForValueButton-message')).not.toBeInTheDocument(); - expect(screen.queryByTestId('addFilterOutValueButton-message')).not.toBeInTheDocument(); - expect(screen.queryByTestId('addExistsFilterButton-message')).not.toBeInTheDocument(); - expect(screen.getByTestId('toggleColumnButton-message')).not.toBeDisabled(); - expect(screen.getByTestId('togglePinFilterButton-message')).not.toBeDisabled(); + const rows: TableRow[] = [ + { + action: { + onFilter: jest.fn(), + flattenedField: 'flattenedField', + onToggleColumn: jest.fn(), + }, + field: { + pinned: true, + onTogglePinned: jest.fn(), + field: 'message', + fieldMapping: new DataViewField({ + type: 'keyword', + name: 'message', + searchable: true, + aggregatable: true, + }), + fieldType: 'keyword', + displayName: 'message', + scripted: false, + }, + value: { + ignored: undefined, + formattedValue: 'test', + }, + }, + ]; + + const Component = () =>

Component
; + const EuiCellParams = { + Component, + rowIndex: 0, + colIndex: 0, + columnId: 'test', + isExpanded: false, + }; + + describe('getFieldCellActions', () => { + it('should render correctly for undefined functions', () => { + expect( + getFieldCellActions({ rows, filter: undefined, onToggleColumn: jest.fn() }).map((item) => + item(EuiCellParams) + ) + ).toMatchSnapshot(); + + expect( + getFieldCellActions({ rows, filter: undefined, onToggleColumn: undefined }).map((item) => + item(EuiCellParams) + ) + ).toMatchSnapshot(); + }); + + it('should render the panels correctly for defined onFilter function', () => { + expect( + getFieldCellActions({ rows, filter: jest.fn(), onToggleColumn: jest.fn() }).map((item) => + item(EuiCellParams) + ) + ).toMatchSnapshot(); + }); }); - it('should render the panels correctly for defined onFilter function', () => { - render( - - ); - expect(screen.getByTestId('addFilterForValueButton-message')).not.toBeDisabled(); - expect(screen.getByTestId('addFilterOutValueButton-message')).not.toBeDisabled(); - expect(screen.getByTestId('addExistsFilterButton-message')).not.toBeDisabled(); - expect(screen.getByTestId('toggleColumnButton-message')).not.toBeDisabled(); - expect(screen.getByTestId('togglePinFilterButton-message')).not.toBeDisabled(); + describe('getFieldValueCellActions', () => { + it('should render correctly for undefined functions', () => { + expect( + getFieldValueCellActions({ rows, filter: undefined }).map((item) => item(EuiCellParams)) + ).toMatchSnapshot(); + }); + + it('should render the panels correctly for defined onFilter function', () => { + expect( + getFieldValueCellActions({ rows, filter: jest.fn() }).map((item) => item(EuiCellParams)) + ).toMatchSnapshot(); + }); }); }); diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx index cfbfd1b1cde03..7814405e09201 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx @@ -6,125 +6,210 @@ * Side Public License, v 1. */ -import React, { useCallback, useState } from 'react'; -import { - EuiButtonIcon, - EuiContextMenu, - EuiPopover, - EuiFlexGroup, - EuiFlexItem, - EuiToolTip, -} from '@elastic/eui'; +import React from 'react'; +import { EuiDataGridColumnCellActionProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { DataViewField } from '@kbn/data-views-plugin/public'; -import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { DocViewFilterFn, FieldRecordLegacy } from '@kbn/unified-doc-viewer/types'; + +export interface TableRow { + action: Omit; + field: { + pinned: boolean; + onTogglePinned: (field: string) => void; + } & FieldRecordLegacy['field']; + value: FieldRecordLegacy['value']; +} interface TableActionsProps { - mode?: 'inline' | 'as_popover'; - field: string; - pinned: boolean; - flattenedField: unknown; - fieldMapping?: DataViewField; - onFilter?: DocViewFilterFn; - onToggleColumn: (field: string) => void; - ignoredValue: boolean; - onTogglePinned: (field: string) => void; + Component: EuiDataGridColumnCellActionProps['Component']; + row: TableRow | undefined; // as we pass `rows[rowIndex]` it's safer to assume that `row` prop can be undefined } -interface PanelItem { - name: string; - 'aria-label': string; - toolTipContent?: string; - disabled?: boolean; - 'data-test-subj': string; - icon: string; - onClick: () => void; +export function isFilterInOutPairDisabled(row: TableRow | undefined): boolean { + if (!row) { + return false; + } + const { + action: { onFilter }, + field: { fieldMapping }, + value: { ignored }, + } = row; + + return Boolean(onFilter && (!fieldMapping || !fieldMapping.filterable || ignored)); } -export const TableActions = ({ - mode = 'as_popover', - pinned, - field, - fieldMapping, - flattenedField, - onToggleColumn, - onFilter, - ignoredValue, - onTogglePinned, -}: TableActionsProps) => { - const [isOpen, setIsOpen] = useState(false); - const openActionsLabel = i18n.translate('unifiedDocViewer.docView.table.actions.open', { - defaultMessage: 'Open actions', - }); - const actionsLabel = i18n.translate('unifiedDocViewer.docView.table.actions.label', { - defaultMessage: 'Actions', - }); +export function getFilterInOutPairDisabledWarning(row: TableRow | undefined): string | undefined { + if (!row || !isFilterInOutPairDisabled(row)) { + return undefined; + } + const { + field: { fieldMapping }, + value: { ignored }, + } = row; + + if (ignored) { + return i18n.translate( + 'unifiedDocViewer.docViews.table.ignoredValuesCanNotBeSearchedWarningMessage', + { + defaultMessage: 'Ignored values cannot be searched', + } + ); + } + + return !fieldMapping + ? i18n.translate( + 'unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedWarningMessage', + { + defaultMessage: 'Unindexed fields cannot be searched', + } + ) + : undefined; +} + +export const FilterIn: React.FC = ({ Component, row }) => { + if (!row) { + return null; + } + + const { + action: { onFilter, flattenedField }, + field: { field, fieldMapping }, + } = row; // Filters pair - const filtersPairDisabled = !fieldMapping || !fieldMapping.filterable || ignoredValue; const filterAddLabel = i18n.translate( 'unifiedDocViewer.docViews.table.filterForValueButtonTooltip', { defaultMessage: 'Filter for value', } ); - const filterAddAriaLabel = i18n.translate( - 'unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel', - { defaultMessage: 'Filter for value' } + + if (!onFilter) { + return null; + } + + return ( + onFilter(fieldMapping, flattenedField, '+')} + > + {filterAddLabel} + ); +}; + +export const FilterOut: React.FC = ({ Component, row }) => { + if (!row) { + return null; + } + + const { + action: { onFilter, flattenedField }, + field: { field, fieldMapping }, + } = row; + + // Filters pair const filterOutLabel = i18n.translate( 'unifiedDocViewer.docViews.table.filterOutValueButtonTooltip', { defaultMessage: 'Filter out value', } ); - const filterOutAriaLabel = i18n.translate( - 'unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel', - { defaultMessage: 'Filter out value' } + + if (!onFilter) { + return null; + } + + return ( + onFilter(fieldMapping, flattenedField, '-')} + > + {filterOutLabel} + ); - const filtersPairToolTip = - (filtersPairDisabled && - i18n.translate('unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip', { - defaultMessage: 'Unindexed fields or ignored values cannot be searched', - })) || - undefined; +}; + +export function isFilterExistsDisabled(row: TableRow | undefined): boolean { + if (!row) { + return false; + } + const { + action: { onFilter }, + field: { fieldMapping }, + } = row; + + return Boolean(onFilter && (!fieldMapping || !fieldMapping.filterable || fieldMapping.scripted)); +} + +export function getFilterExistsDisabledWarning(row: TableRow | undefined): string | undefined { + if (!row || !isFilterExistsDisabled(row)) { + return undefined; + } + const { + field: { fieldMapping }, + } = row; + + return fieldMapping?.scripted + ? i18n.translate( + 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsWarningMessage', + { + defaultMessage: 'Unable to filter for presence of scripted fields', + } + ) + : undefined; +} + +export const FilterExist: React.FC = ({ Component, row }) => { + if (!row) { + return null; + } + + const { + action: { onFilter }, + field: { field }, + } = row; // Filter exists const filterExistsLabel = i18n.translate( 'unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip', { defaultMessage: 'Filter for field present' } ); - const filterExistsAriaLabel = i18n.translate( - 'unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel', - { defaultMessage: 'Filter for field present' } - ); - const filtersExistsDisabled = !fieldMapping || !fieldMapping.filterable; - const filtersExistsToolTip = - (filtersExistsDisabled && - (fieldMapping && fieldMapping.scripted - ? i18n.translate( - 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip', - { - defaultMessage: 'Unable to filter for presence of scripted fields', - } - ) - : i18n.translate( - 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip', - { - defaultMessage: 'Unable to filter for presence of meta fields', - } - ))) || - undefined; - - // Toggle columns - const toggleColumnsLabel = i18n.translate( - 'unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip', - { defaultMessage: 'Toggle column in table' } - ); - const toggleColumnsAriaLabel = i18n.translate( - 'unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel', - { defaultMessage: 'Toggle column in table' } + + if (!onFilter) { + return null; + } + + return ( + onFilter('_exists_', field, '+')} + > + {filterExistsLabel} + ); +}; + +export const PinToggle: React.FC = ({ Component, row }) => { + if (!row) { + return null; + } + + const { + field: { field, pinned, onTogglePinned }, + } = row; // Pinned const pinnedLabel = pinned @@ -134,128 +219,101 @@ export const TableActions = ({ : i18n.translate('unifiedDocViewer.docViews.table.pinFieldLabel', { defaultMessage: 'Pin field', }); - const pinnedAriaLabel = pinned - ? i18n.translate('unifiedDocViewer.docViews.table.unpinFieldAriaLabel', { - defaultMessage: 'Unpin field', - }) - : i18n.translate('unifiedDocViewer.docViews.table.pinFieldAriaLabel', { - defaultMessage: 'Pin field', - }); const pinnedIconType = pinned ? 'pinFilled' : 'pin'; - const toggleOpenPopover = useCallback(() => setIsOpen((current) => !current), []); - const closePopover = useCallback(() => setIsOpen(false), []); - const togglePinned = useCallback(() => onTogglePinned(field), [field, onTogglePinned]); - const onClickAction = useCallback( - (callback: () => void) => () => { - callback(); - closePopover(); - }, - [closePopover] + return ( + onTogglePinned(field)} + > + {pinnedLabel} + ); +}; - let panelItems: PanelItem[] = [ - { - name: toggleColumnsLabel, - 'aria-label': toggleColumnsAriaLabel, - 'data-test-subj': `toggleColumnButton-${field}`, - icon: 'listAdd', - onClick: onClickAction(onToggleColumn.bind({}, field)), - }, - { - name: pinnedLabel, - 'aria-label': pinnedAriaLabel, - icon: pinnedIconType, - 'data-test-subj': `togglePinFilterButton-${field}`, - onClick: onClickAction(togglePinned), - }, - ]; - - if (onFilter) { - panelItems = [ - { - name: filterAddLabel, - 'aria-label': filterAddAriaLabel, - toolTipContent: filtersPairToolTip, - icon: 'plusInCircle', - disabled: filtersPairDisabled, - 'data-test-subj': `addFilterForValueButton-${field}`, - onClick: onClickAction(onFilter.bind({}, fieldMapping, flattenedField, '+')), - }, - { - name: filterOutLabel, - 'aria-label': filterOutAriaLabel, - toolTipContent: filtersPairToolTip, - icon: 'minusInCircle', - disabled: filtersPairDisabled, - 'data-test-subj': `addFilterOutValueButton-${field}`, - onClick: onClickAction(onFilter.bind({}, fieldMapping, flattenedField, '-')), - }, - { - name: filterExistsLabel, - 'aria-label': filterExistsAriaLabel, - toolTipContent: filtersExistsToolTip, - icon: 'filter', - disabled: filtersExistsDisabled, - 'data-test-subj': `addExistsFilterButton-${field}`, - onClick: onClickAction(onFilter.bind({}, '_exists_', field, '+')), - }, - ...panelItems, - ]; +export const ToggleColumn: React.FC = ({ Component, row }) => { + if (!row) { + return null; } - const panels = [ - { - id: 0, - title: actionsLabel, - items: panelItems, - }, - ]; + const { + action: { onToggleColumn }, + field: { field }, + } = row; - if (mode === 'inline') { - return ( - - {panels[0].items.map((item) => ( - - - - - - ))} - - ); + if (!onToggleColumn) { + return null; } + // Toggle column + const toggleColumnLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.toggleColumnTableButtonTooltip', + { + defaultMessage: 'Toggle column in table', + } + ); + return ( - - } - isOpen={isOpen} - closePopover={closePopover} - display="block" - panelPaddingSize="none" + onToggleColumn(field)} > - - + {toggleColumnLabel} + ); }; + +export function getFieldCellActions({ + rows, + filter, + onToggleColumn, +}: { + rows: TableRow[]; + filter?: DocViewFilterFn; + onToggleColumn: ((field: string) => void) | undefined; +}) { + return [ + ...(filter + ? [ + ({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => { + return ; + }, + ] + : []), + ...(onToggleColumn + ? [ + ({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => { + return ; + }, + ] + : []), + ({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => { + return ; + }, + ]; +} + +export function getFieldValueCellActions({ + rows, + filter, +}: { + rows: TableRow[]; + filter?: DocViewFilterFn; +}) { + return filter + ? [ + ({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => { + return ; + }, + ({ Component, rowIndex }: EuiDataGridColumnCellActionProps) => { + return ; + }, + ] + : []; +} diff --git a/src/plugins/unified_doc_viewer/public/components/index.ts b/src/plugins/unified_doc_viewer/public/components/index.ts index b5f3a8948d689..c7a2cef523f76 100644 --- a/src/plugins/unified_doc_viewer/public/components/index.ts +++ b/src/plugins/unified_doc_viewer/public/components/index.ts @@ -7,6 +7,7 @@ */ export * from './doc_viewer'; +export * from './doc_viewer_flyout'; export * from './doc_viewer_source'; export * from './doc_viewer_table'; export * from './json_code_editor'; diff --git a/src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer.tsx b/src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer.tsx new file mode 100644 index 0000000000000..06bbb3e71bde3 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer.tsx @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { withSuspense } from '@kbn/shared-ux-utility'; +import type { DocViewRenderProps } from '@kbn/unified-doc-viewer/src/services/types'; +import { EuiDelayRender, EuiSkeletonText } from '@elastic/eui'; + +const LazyUnifiedDocViewer = React.lazy(() => import('./doc_viewer')); +export const UnifiedDocViewer = withSuspense( + LazyUnifiedDocViewer, + + + +); diff --git a/src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer_flyout.tsx b/src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer_flyout.tsx new file mode 100644 index 0000000000000..e81dfaec2f319 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/lazy_doc_viewer_flyout.tsx @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { withSuspense } from '@kbn/shared-ux-utility'; +import type { UnifiedDocViewerFlyoutProps } from './doc_viewer_flyout/doc_viewer_flyout'; + +const LazyUnifiedDocViewerFlyout = React.lazy(() => import('./doc_viewer_flyout')); +export const UnifiedDocViewerFlyout = withSuspense( + LazyUnifiedDocViewerFlyout, + <> +); diff --git a/src/plugins/unified_doc_viewer/public/index.tsx b/src/plugins/unified_doc_viewer/public/index.tsx index ffe5c3f16d78c..b594d8f06c42f 100644 --- a/src/plugins/unified_doc_viewer/public/index.tsx +++ b/src/plugins/unified_doc_viewer/public/index.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { withSuspense } from '@kbn/shared-ux-utility'; import { EuiDelayRender, EuiSkeletonText } from '@elastic/eui'; -import { DocViewRenderProps } from '@kbn/unified-doc-viewer/src/services/types'; import type { JsonCodeEditorProps } from './components'; import { UnifiedDocViewerPublicPlugin } from './plugin'; @@ -26,14 +25,8 @@ export const JsonCodeEditor = withSuspense( ); -const LazyUnifiedDocViewer = React.lazy(() => import('./components/doc_viewer')); -export const UnifiedDocViewer = withSuspense( - LazyUnifiedDocViewer, - - - -); - export { useEsDocSearch } from './hooks'; +export { UnifiedDocViewer } from './components/lazy_doc_viewer'; +export { UnifiedDocViewerFlyout } from './components/lazy_doc_viewer_flyout'; export const plugin = () => new UnifiedDocViewerPublicPlugin(); diff --git a/src/plugins/unified_doc_viewer/public/plugin.tsx b/src/plugins/unified_doc_viewer/public/plugin.tsx index 524a02eec9ee9..13027a2541084 100644 --- a/src/plugins/unified_doc_viewer/public/plugin.tsx +++ b/src/plugins/unified_doc_viewer/public/plugin.tsx @@ -99,7 +99,7 @@ export class UnifiedDocViewerPublicPlugin defaultMessage: 'JSON', }), order: 20, - component: ({ hit, dataView, textBasedHits }) => { + component: ({ hit, dataView, textBasedHits, decreaseAvailableHeightBy }) => { return ( {}} /> ); diff --git a/src/plugins/unified_doc_viewer/tsconfig.json b/src/plugins/unified_doc_viewer/tsconfig.json index 43cfe7945f188..fbe2ac83c5f1a 100644 --- a/src/plugins/unified_doc_viewer/tsconfig.json +++ b/src/plugins/unified_doc_viewer/tsconfig.json @@ -30,7 +30,9 @@ "@kbn/react-field", "@kbn/ui-theme", "@kbn/discover-shared-plugin", - "@kbn/fields-metadata-plugin" + "@kbn/fields-metadata-plugin", + "@kbn/unified-data-table", + "@kbn/core-notifications-browser" ], "exclude": [ "target/**/*", diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index 454b48b97ebca..abdfe096efab2 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -134,15 +134,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('a11y test for actions on a field', async () => { await PageObjects.discover.clickDocViewerTab('doc_view_table'); - if (await testSubjects.exists('openFieldActionsButton-Cancelled')) { - await testSubjects.click('openFieldActionsButton-Cancelled'); // Open the actions - } else { - await testSubjects.existOrFail('fieldActionsGroup-Cancelled'); - } + await dataGrid.expandFieldNameCellInFlyout('Cancelled'); await a11y.testAppSnapshot(); - if (await testSubjects.exists('openFieldActionsButton-Cancelled')) { - await testSubjects.click('openFieldActionsButton-Cancelled'); // Close the actions - } + await browser.pressKeys(browser.keys.ESCAPE); }); it('a11y test for data-grid table with columns', async () => { diff --git a/test/functional/apps/context/_filters.ts b/test/functional/apps/context/_filters.ts index 9aff3f6c805fc..71cb9eefe2dd2 100644 --- a/test/functional/apps/context/_filters.ts +++ b/test/functional/apps/context/_filters.ts @@ -22,7 +22,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'context']); + const PageObjects = getPageObjects(['common', 'context', 'discover']); const testSubjects = getService('testSubjects'); describe('context filters', function contextSize() { @@ -41,6 +41,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('inclusive filter should be addable via expanded data grid rows', async function () { await retry.waitFor(`filter ${TEST_ANCHOR_FILTER_FIELD} in filterbar`, async () => { await dataGrid.clickRowToggle({ isAnchorRow: true, renderMoreRows: true }); + await PageObjects.discover.findFieldByNameInDocViewer(TEST_ANCHOR_FILTER_FIELD); await dataGrid.clickFieldActionInFlyout( TEST_ANCHOR_FILTER_FIELD, 'addFilterForValueButton' diff --git a/test/functional/apps/dashboard/group1/embeddable_data_grid.ts b/test/functional/apps/dashboard/group1/embeddable_data_grid.ts index 010644b1d2029..0b2199a976d0b 100644 --- a/test/functional/apps/dashboard/group1/embeddable_data_grid.ts +++ b/test/functional/apps/dashboard/group1/embeddable_data_grid.ts @@ -49,7 +49,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async function () { await dataGrid.clickRowToggle({ isAnchorRow: false, rowIndex: 0 }); const detailsEl = await dataGrid.getDetailsRows(); - const defaultMessageEl = await detailsEl[0].findByTestSubject('docTableRowDetailsTitle'); + const defaultMessageEl = await detailsEl[0].findByTestSubject('docViewerRowDetailsTitle'); expect(defaultMessageEl).to.be.ok(); await dataGrid.closeFlyout(); }); diff --git a/test/functional/apps/dashboard/group1/url_field_formatter.ts b/test/functional/apps/dashboard/group1/url_field_formatter.ts index 12863bcc17fc4..b408e0aed14d6 100644 --- a/test/functional/apps/dashboard/group1/url_field_formatter.ts +++ b/test/functional/apps/dashboard/group1/url_field_formatter.ts @@ -19,6 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ]); const kibanaServer = getService('kibanaServer'); const testSubjects = getService('testSubjects'); + const find = getService('find'); const browser = getService('browser'); const fieldName = 'clientip'; const deployment = getService('deployment'); @@ -82,13 +83,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.waitForWithTimeout(`${fieldName} is visible`, 30000, async () => { return await testSubjects.isDisplayed(`tableDocViewRow-${fieldName}-value`); }); - const fieldLink = await testSubjects.find(`tableDocViewRow-${fieldName}-value`); + const fieldLink = await find.byCssSelector( + `[data-test-subj="tableDocViewRow-${fieldName}-value"] a` + ); const fieldValue = await fieldLink.getVisibleText(); await fieldLink.click(); await retry.try(async () => { await checkUrl(fieldValue); }); }); + afterEach(async function () { const windowHandlers = await browser.getAllWindowHandles(); if (windowHandlers.length > 1) { diff --git a/test/functional/apps/discover/classic/_doc_table.ts b/test/functional/apps/discover/classic/_doc_table.ts index 7ab640cf42ee1..7539cce991af8 100644 --- a/test/functional/apps/discover/classic/_doc_table.ts +++ b/test/functional/apps/discover/classic/_doc_table.ts @@ -161,7 +161,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); const detailsEl = await docTable.getDetailsRows(); const defaultMessageEl = await detailsEl[0].findByTestSubject( - 'docTableRowDetailsTitle' + 'docViewerRowDetailsTitle' ); expect(defaultMessageEl).to.be.ok(); }); @@ -187,14 +187,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); const detailsEl = await docTable.getDetailsRows(); const defaultMessageEl = await detailsEl[0].findByTestSubject( - 'docTableRowDetailsTitle' + 'docViewerRowDetailsTitle' ); expect(defaultMessageEl).to.be.ok(); await queryBar.submitQuery(); const nrOfFetchesResubmit = await PageObjects.discover.getNrOfFetches(); expect(nrOfFetchesResubmit).to.be.above(nrOfFetches); const defaultMessageElResubmit = await detailsEl[0].findByTestSubject( - 'docTableRowDetailsTitle' + 'docViewerRowDetailsTitle' ); expect(defaultMessageElResubmit).to.be.ok(); diff --git a/test/functional/apps/discover/classic/_esql_grid.ts b/test/functional/apps/discover/classic/_esql_grid.ts index 7dfd331acec12..d2bacbcd4947a 100644 --- a/test/functional/apps/discover/classic/_esql_grid.ts +++ b/test/functional/apps/discover/classic/_esql_grid.ts @@ -65,7 +65,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dataGrid.clickRowToggle({ rowIndex: 0 }); - await testSubjects.existOrFail('docTableDetailsFlyout'); + await testSubjects.existOrFail('docViewerFlyout'); await PageObjects.discover.saveSearch(savedSearchESQL); @@ -81,7 +81,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dataGrid.clickRowToggle({ rowIndex: 0 }); - await testSubjects.existOrFail('docTableDetailsFlyout'); + await testSubjects.existOrFail('docViewerFlyout'); await dashboardPanelActions.removePanelByTitle(savedSearchESQL); diff --git a/test/functional/apps/discover/group2_data_grid1/_data_grid_doc_table.ts b/test/functional/apps/discover/group2_data_grid1/_data_grid_doc_table.ts index 81fd740ba21fa..ac77fe3f70714 100644 --- a/test/functional/apps/discover/group2_data_grid1/_data_grid_doc_table.ts +++ b/test/functional/apps/discover/group2_data_grid1/_data_grid_doc_table.ts @@ -163,7 +163,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async function () { await dataGrid.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); const detailsEl = await dataGrid.getDetailsRows(); - const defaultMessageEl = await detailsEl[0].findByTestSubject('docTableRowDetailsTitle'); + const defaultMessageEl = await detailsEl[0].findByTestSubject('docViewerRowDetailsTitle'); expect(defaultMessageEl).to.be.ok(); await dataGrid.closeFlyout(); }); @@ -185,9 +185,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should allow paginating docs in the flyout by clicking in the doc table', async function () { await retry.try(async function () { await dataGrid.clickRowToggle({ rowIndex: rowToInspect - 1 }); - await testSubjects.exists(`dscDocNavigationPage0`); + await testSubjects.exists(`docViewerFlyoutNavigationPage0`); await dataGrid.clickRowToggle({ rowIndex: rowToInspect }); - await testSubjects.exists(`dscDocNavigationPage1`); + await testSubjects.exists(`docViewerFlyoutNavigationPage1`); await dataGrid.closeFlyout(); }); }); diff --git a/test/functional/apps/discover/group2_data_grid2/_data_grid_field_tokens.ts b/test/functional/apps/discover/group2_data_grid2/_data_grid_field_tokens.ts index d22e8b39bd4a5..fad92414cfb1c 100644 --- a/test/functional/apps/discover/group2_data_grid2/_data_grid_field_tokens.ts +++ b/test/functional/apps/discover/group2_data_grid2/_data_grid_field_tokens.ts @@ -43,7 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { let fieldTokens: string[] | undefined = []; await retry.try(async () => { await dataGrid.clickRowToggle({ rowIndex: 0 }); - fieldTokens = await findFirstFieldIcons('docTableDetailsFlyout'); + fieldTokens = await findFirstFieldIcons('docViewerFlyout'); }); return fieldTokens; } diff --git a/test/functional/apps/discover/group3/_doc_viewer.ts b/test/functional/apps/discover/group3/_doc_viewer.ts index 8fa3a94b969e3..140129c6a251f 100644 --- a/test/functional/apps/discover/group3/_doc_viewer.ts +++ b/test/functional/apps/discover/group3/_doc_viewer.ts @@ -41,13 +41,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); describe('search', function () { - const itemsPerPage = 25; - beforeEach(async () => { await dataGrid.clickRowToggle(); await PageObjects.discover.isShowingDocViewer(); await retry.waitFor('rendered items', async () => { - return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === itemsPerPage; + return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length > 0; }); }); @@ -95,7 +93,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // expect no changes in the list await retry.waitFor('all items', async () => { - return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length === itemsPerPage; + return (await find.allByCssSelector('.kbnDocViewer__fieldName')).length > 0; }); }); }); diff --git a/test/functional/apps/discover/group7/_runtime_fields_editor.ts b/test/functional/apps/discover/group7/_runtime_fields_editor.ts index de43dc8e74e92..3028096adc60c 100644 --- a/test/functional/apps/discover/group7/_runtime_fields_editor.ts +++ b/test/functional/apps/discover/group7/_runtime_fields_editor.ts @@ -105,7 +105,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // check it in the doc viewer too await dataGrid.clickRowToggle({ rowIndex: 0 }); - await testSubjects.click('fieldDescriptionPopoverButton-agent'); + await dataGrid.expandFieldNameCellInFlyout('agent'); await retry.waitFor('doc viewer popover text', async () => { return (await testSubjects.getVisibleText('fieldDescription-agent')) === customDescription2; }); diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index 18282442696ff..cb225c45d1ea0 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -268,7 +268,7 @@ export class DataGridService extends FtrService { } public async getDetailsRows(): Promise { - return await this.testSubjects.findAll('docTableDetailsFlyout'); + return await this.testSubjects.findAll('docViewerFlyout'); } public async closeFlyout() { @@ -452,17 +452,30 @@ export class DataGridService extends FtrService { return await tableDocViewRow.findByTestSubject(`~removeInclusiveFilterButton`); } + public async showFieldCellActionInFlyout(fieldName: string, actionName: string): Promise { + const cellSelector = ['addFilterForValueButton', 'addFilterOutValueButton'].includes(actionName) + ? `tableDocViewRow-${fieldName}-value` + : `tableDocViewRow-${fieldName}-name`; + await this.testSubjects.click(cellSelector); + await this.retry.waitFor('grid cell actions to appear', async () => { + return this.testSubjects.exists(`${actionName}-${fieldName}`); + }); + } + public async clickFieldActionInFlyout(fieldName: string, actionName: string): Promise { - const openPopoverButtonSelector = `openFieldActionsButton-${fieldName}`; - const inlineButtonsGroupSelector = `fieldActionsGroup-${fieldName}`; - if (await this.testSubjects.exists(openPopoverButtonSelector)) { - await this.testSubjects.click(openPopoverButtonSelector); - } else { - await this.testSubjects.existOrFail(inlineButtonsGroupSelector); - } + await this.showFieldCellActionInFlyout(fieldName, actionName); await this.testSubjects.click(`${actionName}-${fieldName}`); } + public async expandFieldNameCellInFlyout(fieldName: string): Promise { + const buttonSelector = 'euiDataGridCellExpandButton'; + await this.testSubjects.click(`tableDocViewRow-${fieldName}-name`); + await this.retry.waitFor('grid cell actions to appear', async () => { + return this.testSubjects.exists(buttonSelector); + }); + await this.testSubjects.click(buttonSelector); + } + public async hasNoResults() { return await this.find.existsByCssSelector('.euiDataGrid__noResults'); } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index d8143a8c98bf3..57e13f649a365 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2396,12 +2396,12 @@ "discover.fieldChooser.discoverField.removeFieldTooltip": "Supprimer le champ du tableau", "discover.globalSearch.esqlSearchTitle": "Créer des recherches ES|QL", "discover.goToDiscoverButtonText": "Aller à Discover", - "discover.grid.flyout.documentNavigation": "Navigation dans le document", - "discover.grid.flyout.toastColumnAdded": "La colonne \"{columnName}\" a été ajoutée.", - "discover.grid.flyout.toastColumnRemoved": "La colonne \"{columnName}\" a été supprimée.", + "unifiedDocViewer.flyout.documentNavigation": "Navigation dans le document", + "unifiedDocViewer.flyout.toastColumnAdded": "La colonne \"{columnName}\" a été ajoutée.", + "unifiedDocViewer.flyout.toastColumnRemoved": "La colonne \"{columnName}\" a été supprimée.", "discover.grid.tableRow.actionsLabel": "Actions", - "discover.grid.tableRow.docViewerDetailHeading": "Document", - "discover.grid.tableRow.docViewerEsqlDetailHeading": "Ligne", + "unifiedDocViewer.flyout.docViewerDetailHeading": "Document", + "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "Ligne", "discover.grid.tableRow.mobileFlyoutActionsButton": "Actions", "discover.grid.tableRow.moreFlyoutActionsButton": "Plus d'actions", "discover.grid.tableRow.esqlDetailHeading": "Ligne développée", @@ -44235,8 +44235,6 @@ "uiActions.errors.incompatibleAction": "Action non compatible", "uiActions.triggers.rowClickkDescription": "Un clic sur une ligne de tableau", "uiActions.triggers.rowClickTitle": "Clic sur ligne de tableau", - "unifiedDocViewer.docView.table.actions.label": "Actions", - "unifiedDocViewer.docView.table.actions.open": "Actions ouvertes", "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "Une ou plusieurs valeurs dans ce champ sont trop longues et ne peuvent pas être recherchées ni filtrées.", "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "Ce champ comporte une ou plusieurs valeurs mal formées qui ne peuvent pas être recherchées ni filtrées.", "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "Une ou plusieurs valeurs dans ce champ ont été ignorées par Elasticsearch et ne peuvent pas être recherchées ni filtrées.", @@ -44253,7 +44251,6 @@ "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "Exclure la valeur", "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "Contient des valeurs ignorées", "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "Valeur ignorée", - "unifiedDocViewer.docViews.table.pinFieldAriaLabel": "Épingler le champ", "unifiedDocViewer.docViews.table.pinFieldLabel": "Épingler le champ", "unifiedDocViewer.docViews.table.tableTitle": "Tableau", "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "Afficher/Masquer la colonne dans le tableau", @@ -44261,7 +44258,6 @@ "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "Impossible de filtrer sur les champs méta", "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "Impossible de filtrer sur les champs scriptés", "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "Les champs non indexés ou les valeurs ignorées ne peuvent pas être recherchés", - "unifiedDocViewer.docViews.table.unpinFieldAriaLabel": "Désépingler le champ", "unifiedDocViewer.docViews.table.unpinFieldLabel": "Désépingler le champ", "unifiedDocViewer.fieldChooser.discoverField.actions": "Actions", "unifiedDocViewer.fieldChooser.discoverField.multiField": "champ multiple", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f5b22bce86c92..34bfbb83ecfe1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2393,12 +2393,12 @@ "discover.fieldChooser.discoverField.removeFieldTooltip": "フィールドを表から削除", "discover.globalSearch.esqlSearchTitle": "ES|QLクエリを作成", "discover.goToDiscoverButtonText": "Discoverに移動", - "discover.grid.flyout.documentNavigation": "ドキュメントナビゲーション", - "discover.grid.flyout.toastColumnAdded": "列'{columnName}'が追加されました", - "discover.grid.flyout.toastColumnRemoved": "列'{columnName}'が削除されました", + "unifiedDocViewer.flyout.documentNavigation": "ドキュメントナビゲーション", + "unifiedDocViewer.flyout.toastColumnAdded": "列'{columnName}'が追加されました", + "unifiedDocViewer.flyout.toastColumnRemoved": "列'{columnName}'が削除されました", "discover.grid.tableRow.actionsLabel": "アクション", - "discover.grid.tableRow.docViewerDetailHeading": "ドキュメント", - "discover.grid.tableRow.docViewerEsqlDetailHeading": "行", + "unifiedDocViewer.flyout.docViewerDetailHeading": "ドキュメント", + "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "行", "discover.grid.tableRow.mobileFlyoutActionsButton": "アクション", "discover.grid.tableRow.moreFlyoutActionsButton": "さらにアクションを表示", "discover.grid.tableRow.esqlDetailHeading": "展開された行", @@ -44211,8 +44211,6 @@ "uiActions.errors.incompatibleAction": "操作に互換性がありません", "uiActions.triggers.rowClickkDescription": "テーブル行をクリック", "uiActions.triggers.rowClickTitle": "テーブル行クリック", - "unifiedDocViewer.docView.table.actions.label": "アクション", - "unifiedDocViewer.docView.table.actions.open": "アクションを開く", "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "このフィールドの1つ以上の値が長すぎるため、検索またはフィルタリングできません。", "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "このフィールドは、検索またはフィルタリングできない正しくない形式の値が1つ以上あります。", "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "このフィールドの1つ以上の値がElasticsearchによって無視されたため、検索またはフィルタリングできません。", @@ -44229,7 +44227,6 @@ "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "値を除外", "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "無視された値を含む", "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "無視された値", - "unifiedDocViewer.docViews.table.pinFieldAriaLabel": "フィールドを固定", "unifiedDocViewer.docViews.table.pinFieldLabel": "フィールドを固定", "unifiedDocViewer.docViews.table.tableTitle": "表", "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "表の列を切り替える", @@ -44237,7 +44234,6 @@ "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "メタフィールドの有無でフィルタリングできません", "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "スクリプトフィールドの有無でフィルタリングできません", "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "インデックスがないフィールドまたは無視された値は検索できません", - "unifiedDocViewer.docViews.table.unpinFieldAriaLabel": "フィールドを固定解除", "unifiedDocViewer.docViews.table.unpinFieldLabel": "フィールドを固定解除", "unifiedDocViewer.fieldChooser.discoverField.actions": "アクション", "unifiedDocViewer.fieldChooser.discoverField.multiField": "複数フィールド", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d94eb2aed9eb7..2b6307f7417bb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2397,12 +2397,12 @@ "discover.fieldChooser.discoverField.removeFieldTooltip": "从表中移除字段", "discover.globalSearch.esqlSearchTitle": "创建 ES|QL 查询", "discover.goToDiscoverButtonText": "前往 Discover", - "discover.grid.flyout.documentNavigation": "文档导航", - "discover.grid.flyout.toastColumnAdded": "已添加列“{columnName}”", - "discover.grid.flyout.toastColumnRemoved": "已移除列“{columnName}”", + "unifiedDocViewer.flyout.documentNavigation": "文档导航", + "unifiedDocViewer.flyout.toastColumnAdded": "已添加列“{columnName}”", + "unifiedDocViewer.flyout.toastColumnRemoved": "已移除列“{columnName}”", "discover.grid.tableRow.actionsLabel": "操作", - "discover.grid.tableRow.docViewerDetailHeading": "文档", - "discover.grid.tableRow.docViewerEsqlDetailHeading": "行", + "unifiedDocViewer.flyout.docViewerDetailHeading": "文档", + "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "行", "discover.grid.tableRow.mobileFlyoutActionsButton": "操作", "discover.grid.tableRow.moreFlyoutActionsButton": "更多操作", "discover.grid.tableRow.esqlDetailHeading": "已展开行", @@ -44259,8 +44259,6 @@ "uiActions.errors.incompatibleAction": "操作不兼容", "uiActions.triggers.rowClickkDescription": "表格行的单击", "uiActions.triggers.rowClickTitle": "表格行单击", - "unifiedDocViewer.docView.table.actions.label": "操作", - "unifiedDocViewer.docView.table.actions.open": "打开操作", "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "此字段中的一个或多个值过长,无法搜索或筛选。", "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "此字段包含一个或多个格式错误的值,无法搜索或筛选。", "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "此字段中的一个或多个值被 Elasticsearch 忽略,无法搜索或筛选。", @@ -44277,7 +44275,6 @@ "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "筛除值", "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "包含被忽略的值", "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "被忽略的值", - "unifiedDocViewer.docViews.table.pinFieldAriaLabel": "固定字段", "unifiedDocViewer.docViews.table.pinFieldLabel": "固定字段", "unifiedDocViewer.docViews.table.tableTitle": "表", "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "在表中切换列", @@ -44285,7 +44282,6 @@ "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "无法筛选元数据字段是否存在", "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "无法筛选脚本字段是否存在", "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "无法搜索未编入索引的字段或被忽略的值", - "unifiedDocViewer.docViews.table.unpinFieldAriaLabel": "取消固定字段", "unifiedDocViewer.docViews.table.unpinFieldLabel": "取消固定字段", "unifiedDocViewer.fieldChooser.discoverField.actions": "操作", "unifiedDocViewer.fieldChooser.discoverField.multiField": "多字段", diff --git a/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts b/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts index 47f864787e6c5..95197c1e20bd6 100644 --- a/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts +++ b/x-pack/test_serverless/functional/test_suites/common/context/_filters.ts @@ -21,7 +21,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'context', 'svlCommonPage']); + const PageObjects = getPageObjects(['common', 'context', 'svlCommonPage', 'discover']); const testSubjects = getService('testSubjects'); describe('context filters', function contextSize() { @@ -42,6 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('inclusive filter should be addable via expanded data grid rows', async function () { await retry.waitFor(`filter ${TEST_ANCHOR_FILTER_FIELD} in filterbar`, async () => { await dataGrid.clickRowToggle({ isAnchorRow: true, renderMoreRows: true }); + await PageObjects.discover.findFieldByNameInDocViewer(TEST_ANCHOR_FILTER_FIELD); await dataGrid.clickFieldActionInFlyout( TEST_ANCHOR_FILTER_FIELD, 'addFilterForValueButton' diff --git a/x-pack/test_serverless/functional/test_suites/common/discover/group2/_data_grid_doc_table.ts b/x-pack/test_serverless/functional/test_suites/common/discover/group2/_data_grid_doc_table.ts index 2ca4c5f856937..5b66781ff2ba7 100644 --- a/x-pack/test_serverless/functional/test_suites/common/discover/group2/_data_grid_doc_table.ts +++ b/x-pack/test_serverless/functional/test_suites/common/discover/group2/_data_grid_doc_table.ts @@ -164,7 +164,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async function () { await dataGrid.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); const detailsEl = await dataGrid.getDetailsRows(); - const defaultMessageEl = await detailsEl[0].findByTestSubject('docTableRowDetailsTitle'); + const defaultMessageEl = await detailsEl[0].findByTestSubject('docViewerRowDetailsTitle'); expect(defaultMessageEl).to.be.ok(); await dataGrid.closeFlyout(); }); @@ -186,9 +186,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should allow paginating docs in the flyout by clicking in the doc table', async function () { await retry.try(async function () { await dataGrid.clickRowToggle({ rowIndex: rowToInspect - 1 }); - await testSubjects.exists(`dscDocNavigationPage0`); + await testSubjects.exists(`docViewerFlyoutNavigationPage0`); await dataGrid.clickRowToggle({ rowIndex: rowToInspect }); - await testSubjects.exists(`dscDocNavigationPage1`); + await testSubjects.exists(`docViewerFlyoutNavigationPage1`); await dataGrid.closeFlyout(); }); }); From 6d39b8a432a427497631f6bf6be23d0d9bb94126 Mon Sep 17 00:00:00 2001 From: Devon Thomson Date: Wed, 19 Jun 2024 10:05:27 -0400 Subject: [PATCH 115/127] [Embeddables Rebuild] Fix runtime state types. (#186194) Fixes runtime state types, requiring them to be specified twice. --- .../get_control_group_factory.tsx | 6 +- .../react_controls/control_group/types.ts | 2 +- .../public/app/render_examples.tsx | 2 +- .../data_table_react_embeddable.tsx | 4 +- .../react_embeddables/data_table/types.ts | 2 + .../eui_markdown_react_embeddable.tsx | 7 +- .../react_embeddables/eui_markdown/types.ts | 2 + .../field_list_react_embeddable.tsx | 8 +- .../react_embeddables/field_list/types.ts | 9 +- .../saved_book_react_embeddable.tsx | 4 +- .../react_embeddables/saved_book/types.ts | 2 +- .../search/search_react_embeddable.tsx | 4 +- .../public/react_embeddables/search/types.ts | 2 + .../public/filter_debugger_embeddable.tsx | 2 +- .../react_embeddable_registry.ts | 20 +- .../react_embeddable_renderer.tsx | 21 +- .../react_embeddable_state.ts | 9 +- .../public/react_embeddable_system/types.ts | 25 +- .../get_image_embeddable_factory.tsx | 1 + .../embeddable_change_point_chart_factory.tsx | 4 +- .../plugins/maps/public/lens/passive_map.tsx | 4 +- .../react_embeddable/map_react_embeddable.tsx | 8 +- .../public/react_embeddable/map_renderer.tsx | 4 +- .../maps/public/react_embeddable/types.ts | 2 + .../anomaly_charts_embeddable_factory.tsx | 285 +++++++++--------- ...omaly_swimlane_embeddable_factory.test.tsx | 6 +- .../anomaly_swimlane_embeddable_factory.tsx | 4 +- ...ingle_metric_viewer_embeddable_factory.tsx | 4 +- .../shared_components/anomaly_swim_lane.tsx | 6 +- .../react_embeddable_factory.tsx | 1 + .../react_embeddable_factory.tsx | 1 + .../react_embeddable_factory.tsx | 1 + .../log_stream_react_embeddable.tsx | 6 +- .../alerts/slo_alerts_embeddable_factory.tsx | 6 +- .../error_budget_react_embeddable_factory.tsx | 6 +- .../slo/overview/slo_embeddable_factory.tsx | 6 +- 36 files changed, 287 insertions(+), 199 deletions(-) diff --git a/examples/controls_example/public/react_controls/control_group/get_control_group_factory.tsx b/examples/controls_example/public/react_controls/control_group/get_control_group_factory.tsx index 703d31f18db1d..d78feb6743795 100644 --- a/examples/controls_example/public/react_controls/control_group/get_control_group_factory.tsx +++ b/examples/controls_example/public/react_controls/control_group/get_control_group_factory.tsx @@ -52,8 +52,8 @@ export const getControlGroupEmbeddableFactory = (services: { }) => { const controlGroupEmbeddableFactory: ReactEmbeddableFactory< ControlGroupSerializedState, - ControlGroupApi, - ControlGroupRuntimeState + ControlGroupRuntimeState, + ControlGroupApi > = { type: CONTROL_GROUP_TYPE, deserializeState: (state) => deserializeControlGroup(state), @@ -117,7 +117,7 @@ export const getControlGroupEmbeddableFactory = (services: { }, snapshotRuntimeState: () => { // TODO: Remove this if it ends up being unnecessary - return {} as unknown as ControlGroupSerializedState; + return {} as unknown as ControlGroupRuntimeState; }, dataLoading: dataLoading$, children$: children$ as PublishingSubject<{ diff --git a/examples/controls_example/public/react_controls/control_group/types.ts b/examples/controls_example/public/react_controls/control_group/types.ts index b1807d31d801b..9fb6af3cef803 100644 --- a/examples/controls_example/public/react_controls/control_group/types.ts +++ b/examples/controls_example/public/react_controls/control_group/types.ts @@ -42,7 +42,7 @@ export type ControlGroupUnsavedChanges = Omit< export type ControlPanelState = DefaultControlState & { type: string; order: number }; export type ControlGroupApi = PresentationContainer & - DefaultEmbeddableApi & + DefaultEmbeddableApi & PublishesFilters & PublishesDataViews & HasSerializedChildState & diff --git a/examples/embeddable_examples/public/app/render_examples.tsx b/examples/embeddable_examples/public/app/render_examples.tsx index 4998b3bc5a59c..7e268e29f620e 100644 --- a/examples/embeddable_examples/public/app/render_examples.tsx +++ b/examples/embeddable_examples/public/app/render_examples.tsx @@ -98,7 +98,7 @@ export const RenderExamples = () => { - + key={hidePanelChrome ? 'hideChrome' : 'showChrome'} type={SEARCH_EMBEDDABLE_ID} getParentApi={() => parentApi} diff --git a/examples/embeddable_examples/public/react_embeddables/data_table/data_table_react_embeddable.tsx b/examples/embeddable_examples/public/react_embeddables/data_table/data_table_react_embeddable.tsx index 3bf161bd51490..d373a00896346 100644 --- a/examples/embeddable_examples/public/react_embeddables/data_table/data_table_react_embeddable.tsx +++ b/examples/embeddable_examples/public/react_embeddables/data_table/data_table_react_embeddable.tsx @@ -26,12 +26,12 @@ import { BehaviorSubject } from 'rxjs'; import { StartDeps } from '../../plugin'; import { DATA_TABLE_ID } from './constants'; import { initializeDataTableQueries } from './data_table_queries'; -import { DataTableApi, DataTableSerializedState } from './types'; +import { DataTableApi, DataTableRuntimeState, DataTableSerializedState } from './types'; export const getDataTableFactory = ( core: CoreStart, services: StartDeps -): ReactEmbeddableFactory => ({ +): ReactEmbeddableFactory => ({ type: DATA_TABLE_ID, deserializeState: (state) => { return state.rawState as DataTableSerializedState; diff --git a/examples/embeddable_examples/public/react_embeddables/data_table/types.ts b/examples/embeddable_examples/public/react_embeddables/data_table/types.ts index d693577bc89fb..787bda380bcfa 100644 --- a/examples/embeddable_examples/public/react_embeddables/data_table/types.ts +++ b/examples/embeddable_examples/public/react_embeddables/data_table/types.ts @@ -15,4 +15,6 @@ import { export type DataTableSerializedState = SerializedTitles & SerializedTimeRange; +export type DataTableRuntimeState = DataTableSerializedState; + export type DataTableApi = DefaultEmbeddableApi & PublishesDataLoading; diff --git a/examples/embeddable_examples/public/react_embeddables/eui_markdown/eui_markdown_react_embeddable.tsx b/examples/embeddable_examples/public/react_embeddables/eui_markdown/eui_markdown_react_embeddable.tsx index 64cdf1cb06e08..cd36c6dc5f1c9 100644 --- a/examples/embeddable_examples/public/react_embeddables/eui_markdown/eui_markdown_react_embeddable.tsx +++ b/examples/embeddable_examples/public/react_embeddables/eui_markdown/eui_markdown_react_embeddable.tsx @@ -19,10 +19,15 @@ import { euiThemeVars } from '@kbn/ui-theme'; import React from 'react'; import { BehaviorSubject } from 'rxjs'; import { EUI_MARKDOWN_ID } from './constants'; -import { MarkdownEditorSerializedState, MarkdownEditorApi } from './types'; +import { + MarkdownEditorApi, + MarkdownEditorRuntimeState, + MarkdownEditorSerializedState, +} from './types'; export const markdownEmbeddableFactory: ReactEmbeddableFactory< MarkdownEditorSerializedState, + MarkdownEditorRuntimeState, MarkdownEditorApi > = { type: EUI_MARKDOWN_ID, diff --git a/examples/embeddable_examples/public/react_embeddables/eui_markdown/types.ts b/examples/embeddable_examples/public/react_embeddables/eui_markdown/types.ts index 31678aa4a2a33..b341ffab1640c 100644 --- a/examples/embeddable_examples/public/react_embeddables/eui_markdown/types.ts +++ b/examples/embeddable_examples/public/react_embeddables/eui_markdown/types.ts @@ -13,4 +13,6 @@ export type MarkdownEditorSerializedState = SerializedTitles & { content: string; }; +export type MarkdownEditorRuntimeState = MarkdownEditorSerializedState; + export type MarkdownEditorApi = DefaultEmbeddableApi; diff --git a/examples/embeddable_examples/public/react_embeddables/field_list/field_list_react_embeddable.tsx b/examples/embeddable_examples/public/react_embeddables/field_list/field_list_react_embeddable.tsx index 2931760310c2b..6c296b00786e9 100644 --- a/examples/embeddable_examples/public/react_embeddables/field_list/field_list_react_embeddable.tsx +++ b/examples/embeddable_examples/public/react_embeddables/field_list/field_list_react_embeddable.tsx @@ -25,7 +25,12 @@ import { cloneDeep } from 'lodash'; import React, { useEffect } from 'react'; import { BehaviorSubject, skip, Subscription, switchMap } from 'rxjs'; import { FIELD_LIST_DATA_VIEW_REF_NAME, FIELD_LIST_ID } from './constants'; -import { FieldListApi, Services, FieldListSerializedStateState } from './types'; +import { + FieldListApi, + Services, + FieldListSerializedStateState, + FieldListRuntimeState, +} from './types'; const DataViewPicker = withSuspense(LazyDataViewPicker, null); @@ -46,6 +51,7 @@ export const getFieldListFactory = ( ) => { const fieldListEmbeddableFactory: ReactEmbeddableFactory< FieldListSerializedStateState, + FieldListRuntimeState, FieldListApi > = { type: FIELD_LIST_ID, diff --git a/examples/embeddable_examples/public/react_embeddables/field_list/types.ts b/examples/embeddable_examples/public/react_embeddables/field_list/types.ts index 0da67bcd0f70b..781f43754228c 100644 --- a/examples/embeddable_examples/public/react_embeddables/field_list/types.ts +++ b/examples/embeddable_examples/public/react_embeddables/field_list/types.ts @@ -19,7 +19,14 @@ export type FieldListSerializedStateState = SerializedTitles & { selectedFieldNames?: string[]; }; -export type FieldListApi = DefaultEmbeddableApi & PublishesSelectedFields & PublishesDataViews; +export type FieldListRuntimeState = FieldListSerializedStateState; + +export type FieldListApi = DefaultEmbeddableApi< + FieldListSerializedStateState, + FieldListSerializedStateState +> & + PublishesSelectedFields & + PublishesDataViews; export interface Services { dataViews: DataViewsPublicPluginStart; diff --git a/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx b/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx index 94e54b6ee350c..0a9c3c4d7117b 100644 --- a/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx +++ b/examples/embeddable_examples/public/react_embeddables/saved_book/saved_book_react_embeddable.tsx @@ -41,8 +41,8 @@ const bookSerializedStateIsByReference = ( export const getSavedBookEmbeddableFactory = (core: CoreStart) => { const savedBookEmbeddableFactory: ReactEmbeddableFactory< BookSerializedState, - BookApi, - BookRuntimeState + BookRuntimeState, + BookApi > = { type: SAVED_BOOK_ID, deserializeState: async (serializedState) => { diff --git a/examples/embeddable_examples/public/react_embeddables/saved_book/types.ts b/examples/embeddable_examples/public/react_embeddables/saved_book/types.ts index ec855bbd38f96..362d95604cf97 100644 --- a/examples/embeddable_examples/public/react_embeddables/saved_book/types.ts +++ b/examples/embeddable_examples/public/react_embeddables/saved_book/types.ts @@ -45,6 +45,6 @@ export interface BookRuntimeState Partial, SerializedTitles {} -export type BookApi = DefaultEmbeddableApi & +export type BookApi = DefaultEmbeddableApi & HasEditCapabilities & HasInPlaceLibraryTransforms; diff --git a/examples/embeddable_examples/public/react_embeddables/search/search_react_embeddable.tsx b/examples/embeddable_examples/public/react_embeddables/search/search_react_embeddable.tsx index 2b789a17da4ae..ef73c179b8f8e 100644 --- a/examples/embeddable_examples/public/react_embeddables/search/search_react_embeddable.tsx +++ b/examples/embeddable_examples/public/react_embeddables/search/search_react_embeddable.tsx @@ -21,10 +21,10 @@ import React, { useEffect } from 'react'; import { BehaviorSubject, switchMap, tap } from 'rxjs'; import { SEARCH_EMBEDDABLE_ID } from './constants'; import { getCount } from './get_count'; -import { SearchApi, Services, SearchSerializedState } from './types'; +import { SearchApi, Services, SearchSerializedState, SearchRuntimeState } from './types'; export const getSearchEmbeddableFactory = (services: Services) => { - const factory: ReactEmbeddableFactory = { + const factory: ReactEmbeddableFactory = { type: SEARCH_EMBEDDABLE_ID, deserializeState: (state) => state.rawState, buildEmbeddable: async (state, buildApi, uuid, parentApi) => { diff --git a/examples/embeddable_examples/public/react_embeddables/search/types.ts b/examples/embeddable_examples/public/react_embeddables/search/types.ts index 835b2380d46a7..c82213931a002 100644 --- a/examples/embeddable_examples/public/react_embeddables/search/types.ts +++ b/examples/embeddable_examples/public/react_embeddables/search/types.ts @@ -20,6 +20,8 @@ import { export type SearchSerializedState = SerializedTimeRange; +export type SearchRuntimeState = SearchSerializedState; + export type SearchApi = DefaultEmbeddableApi & PublishesDataViews & PublishesDataLoading & diff --git a/examples/portable_dashboards_example/public/filter_debugger_embeddable.tsx b/examples/portable_dashboards_example/public/filter_debugger_embeddable.tsx index fd2c23731011b..8c5d136640b1d 100644 --- a/examples/portable_dashboards_example/public/filter_debugger_embeddable.tsx +++ b/examples/portable_dashboards_example/public/filter_debugger_embeddable.tsx @@ -18,7 +18,7 @@ import { FILTER_DEBUGGER_EMBEDDABLE_ID } from './constants'; export type Api = DefaultEmbeddableApi<{}>; -export const factory: ReactEmbeddableFactory<{}, Api> = { +export const factory: ReactEmbeddableFactory<{}, {}, Api> = { type: FILTER_DEBUGGER_EMBEDDABLE_ID, deserializeState: () => { return {}; diff --git a/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_registry.ts b/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_registry.ts index b1d67cc8a1d90..eea89f191db82 100644 --- a/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_registry.ts +++ b/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_registry.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { DefaultEmbeddableApi, ReactEmbeddableFactory } from './types'; -const registry: { [key: string]: () => Promise> } = {}; +const registry: { [key: string]: () => Promise> } = {}; /** * Registers a new React embeddable factory. This should be called at plugin start time. @@ -20,11 +20,14 @@ const registry: { [key: string]: () => Promise> */ export const registerReactEmbeddableFactory = < SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi, - RuntimeState extends object = SerializedState + RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + > >( type: string, - getFactory: () => Promise> + getFactory: () => Promise> ) => { if (registry[type] !== undefined) throw new Error( @@ -40,11 +43,14 @@ export const reactEmbeddableRegistryHasKey = (key: string) => registry[key] !== export const getReactEmbeddableFactory = async < SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi, - RuntimeState extends object = SerializedState + RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + > >( key: string -): Promise> => { +): Promise> => { if (registry[key] === undefined) throw new Error( i18n.translate('embeddableApi.reactEmbeddable.factoryNotFoundError', { diff --git a/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx b/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx index 8d8a632caec1f..002328cf22274 100644 --- a/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx +++ b/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx @@ -38,8 +38,11 @@ const ON_STATE_CHANGE_DEBOUNCE = 100; */ export const ReactEmbeddableRenderer = < SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi, RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + >, ParentApi extends HasSerializedChildState = HasSerializedChildState >({ type, @@ -95,11 +98,11 @@ export const ReactEmbeddableRenderer = < */ return (async () => { const parentApi = getParentApi(); - const factory = await getReactEmbeddableFactory(type); + const factory = await getReactEmbeddableFactory(type); const subscriptions = new Subscription(); const setApi = ( - apiRegistration: SetReactEmbeddableApiRegistration + apiRegistration: SetReactEmbeddableApiRegistration ) => { const fullApi = { ...apiRegistration, @@ -115,12 +118,16 @@ export const ReactEmbeddableRenderer = < const buildEmbeddable = async () => { const { initialState, startStateDiffing } = await initializeReactEmbeddableState< SerializedState, - Api, - RuntimeState + RuntimeState, + Api >(uuid, factory, parentApi); const buildApi = ( - apiRegistration: BuildReactEmbeddableApiRegistration, + apiRegistration: BuildReactEmbeddableApiRegistration< + SerializedState, + RuntimeState, + Api + >, comparators: StateComparators ) => { if (onAnyStateChange) { @@ -160,7 +167,7 @@ export const ReactEmbeddableRenderer = < unsavedChanges, resetUnsavedChanges, snapshotRuntimeState, - } as unknown as SetReactEmbeddableApiRegistration); + } as unknown as SetReactEmbeddableApiRegistration); cleanupFunction.current = () => cleanup(); return fullApi; diff --git a/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_state.ts b/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_state.ts index 605b8d20a7cd1..ddfaf10953821 100644 --- a/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_state.ts +++ b/src/plugins/embeddable/public/react_embeddable_system/react_embeddable_state.ts @@ -29,11 +29,14 @@ import { DefaultEmbeddableApi, ReactEmbeddableFactory } from './types'; export const initializeReactEmbeddableState = async < SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi, - RuntimeState extends object = SerializedState + RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + > >( uuid: string, - factory: ReactEmbeddableFactory, + factory: ReactEmbeddableFactory, parentApi: HasSerializedChildState ) => { const lastSavedRuntimeState = await factory.deserializeState( diff --git a/src/plugins/embeddable/public/react_embeddable_system/types.ts b/src/plugins/embeddable/public/react_embeddable_system/types.ts index 8a05698934e9c..cc4b9cf9b7976 100644 --- a/src/plugins/embeddable/public/react_embeddable_system/types.ts +++ b/src/plugins/embeddable/public/react_embeddable_system/types.ts @@ -41,7 +41,11 @@ export interface DefaultEmbeddableApi< */ export type SetReactEmbeddableApiRegistration< SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi + RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + > > = Omit; /** @@ -50,9 +54,13 @@ export type SetReactEmbeddableApiRegistration< */ export type BuildReactEmbeddableApiRegistration< SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi + RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + > > = Omit< - SetReactEmbeddableApiRegistration, + SetReactEmbeddableApiRegistration, 'unsavedChanges' | 'resetUnsavedChanges' | 'snapshotRuntimeState' >; @@ -65,8 +73,11 @@ export type BuildReactEmbeddableApiRegistration< **/ export interface ReactEmbeddableFactory< SerializedState extends object = object, - Api extends DefaultEmbeddableApi = DefaultEmbeddableApi, - RuntimeState extends object = SerializedState + RuntimeState extends object = SerializedState, + Api extends DefaultEmbeddableApi = DefaultEmbeddableApi< + SerializedState, + RuntimeState + > > { /** * A unique key for the type of this embeddable. The React Embeddable Renderer will use this type @@ -101,12 +112,12 @@ export interface ReactEmbeddableFactory< * changes logic that the dashboard expects using the provided comparators */ buildApi: ( - apiRegistration: BuildReactEmbeddableApiRegistration, + apiRegistration: BuildReactEmbeddableApiRegistration, comparators: StateComparators ) => Api, uuid: string, parentApi: unknown | undefined, /** `setApi` should be used when the unsaved changes logic in `buildApi` is unnecessary */ - setApi: (api: SetReactEmbeddableApiRegistration) => Api + setApi: (api: SetReactEmbeddableApiRegistration) => Api ) => Promise<{ Component: React.FC<{}>; api: Api }>; } diff --git a/src/plugins/image_embeddable/public/image_embeddable/get_image_embeddable_factory.tsx b/src/plugins/image_embeddable/public/image_embeddable/get_image_embeddable_factory.tsx index d5b15122f70f1..2bbff60a50efe 100644 --- a/src/plugins/image_embeddable/public/image_embeddable/get_image_embeddable_factory.tsx +++ b/src/plugins/image_embeddable/public/image_embeddable/get_image_embeddable_factory.tsx @@ -30,6 +30,7 @@ export const getImageEmbeddableFactory = ({ embeddableEnhanced?: EmbeddableEnhancedPluginStart; }) => { const imageEmbeddableFactory: ReactEmbeddableFactory< + ImageEmbeddableSerializedState, ImageEmbeddableSerializedState, ImageEmbeddableApi > = { diff --git a/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx b/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx index 5b8345dd28d39..7e0e00b7ac02d 100644 --- a/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx +++ b/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx @@ -68,8 +68,8 @@ export const getChangePointChartEmbeddableFactory = ( ) => { const factory: ReactEmbeddableFactory< ChangePointEmbeddableState, - ChangePointEmbeddableApi, - ChangePointEmbeddableRuntimeState + ChangePointEmbeddableRuntimeState, + ChangePointEmbeddableApi > = { type: EMBEDDABLE_CHANGE_POINT_CHART_TYPE, deserializeState: (state) => { diff --git a/x-pack/plugins/maps/public/lens/passive_map.tsx b/x-pack/plugins/maps/public/lens/passive_map.tsx index fc2a9c3393733..30a4b8013b8ab 100644 --- a/x-pack/plugins/maps/public/lens/passive_map.tsx +++ b/x-pack/plugins/maps/public/lens/passive_map.tsx @@ -12,7 +12,7 @@ import { ReactEmbeddableRenderer, ViewMode } from '@kbn/embeddable-plugin/public import type { LayerDescriptor } from '../../common/descriptor_types'; import { INITIAL_LOCATION, MAP_SAVED_OBJECT_TYPE } from '../../common'; import { createBasemapLayerDescriptor } from '../classes/layers/create_basemap_layer_descriptor'; -import { MapApi, MapSerializedState } from '../react_embeddable/types'; +import { MapApi, MapRuntimeState, MapSerializedState } from '../react_embeddable/types'; export interface Props { passiveLayer: LayerDescriptor; @@ -50,7 +50,7 @@ export function PassiveMap(props: Props) { return (
- + type={MAP_SAVED_OBJECT_TYPE} getParentApi={() => ({ getSerializedStateForChild: () => { diff --git a/x-pack/plugins/maps/public/react_embeddable/map_react_embeddable.tsx b/x-pack/plugins/maps/public/react_embeddable/map_react_embeddable.tsx index b8028caac41f8..415e3819cdadb 100644 --- a/x-pack/plugins/maps/public/react_embeddable/map_react_embeddable.tsx +++ b/x-pack/plugins/maps/public/react_embeddable/map_react_embeddable.tsx @@ -22,7 +22,7 @@ import { BehaviorSubject } from 'rxjs'; import { apiPublishesSettings } from '@kbn/presentation-containers/interfaces/publishes_settings'; import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; import { inject } from '../../common/embeddable'; -import type { MapApi, MapSerializedState } from './types'; +import type { MapApi, MapRuntimeState, MapSerializedState } from './types'; import { SavedMap } from '../routes/map_page'; import { initializeReduxSync } from './initialize_redux_sync'; import { @@ -44,7 +44,11 @@ export function getControlledBy(id: string) { return `mapEmbeddablePanel${id}`; } -export const mapEmbeddableFactory: ReactEmbeddableFactory = { +export const mapEmbeddableFactory: ReactEmbeddableFactory< + MapSerializedState, + MapRuntimeState, + MapApi +> = { type: MAP_SAVED_OBJECT_TYPE, deserializeState: (state) => { return state.rawState diff --git a/x-pack/plugins/maps/public/react_embeddable/map_renderer.tsx b/x-pack/plugins/maps/public/react_embeddable/map_renderer.tsx index 27dc202e778b0..7701c7ebbe11b 100644 --- a/x-pack/plugins/maps/public/react_embeddable/map_renderer.tsx +++ b/x-pack/plugins/maps/public/react_embeddable/map_renderer.tsx @@ -11,7 +11,7 @@ import { ReactEmbeddableRenderer } from '@kbn/embeddable-plugin/public'; import { useSearchApi } from '@kbn/presentation-publishing'; import type { LayerDescriptor, MapCenterAndZoom, MapSettings } from '../../common/descriptor_types'; import { createBasemapLayerDescriptor } from '../classes/layers/create_basemap_layer_descriptor'; -import { MapApi, MapSerializedState } from './types'; +import { MapApi, MapRuntimeState, MapSerializedState } from './types'; import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; import { RenderToolTipContent } from '../classes/tooltips/tooltip_property'; @@ -58,7 +58,7 @@ export function MapRenderer(props: Props) { return (
- + type={MAP_SAVED_OBJECT_TYPE} getParentApi={() => ({ ...searchApi, diff --git a/x-pack/plugins/maps/public/react_embeddable/types.ts b/x-pack/plugins/maps/public/react_embeddable/types.ts index c650c51b22ddc..f020e75723c6c 100644 --- a/x-pack/plugins/maps/public/react_embeddable/types.ts +++ b/x-pack/plugins/maps/public/react_embeddable/types.ts @@ -58,6 +58,8 @@ export type MapSerializedState = SerializedTitles & tooltipRenderer?: RenderToolTipContent; }; +export type MapRuntimeState = MapSerializedState; + export type MapApi = DefaultEmbeddableApi & HasDynamicActions & Partial & diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx index 1dc792ffc44bf..3f5afc4065e1f 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx @@ -37,161 +37,164 @@ import { buildDataViewPublishingApi } from '../common/anomaly_detection_embeddab export const getAnomalyChartsReactEmbeddableFactory = ( getStartServices: StartServicesAccessor ) => { - const factory: ReactEmbeddableFactory = - { - type: ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, - deserializeState: (state) => state.rawState, - buildEmbeddable: async (state, buildApi, uuid, parentApi) => { - if (!apiHasExecutionContext(parentApi)) { - throw new Error('Parent API does not have execution context'); - } - const [coreStartServices, pluginsStartServices] = await getStartServices(); - const anomalyChartsDependencies = await getAnomalyChartsServiceDependencies( - coreStartServices, - pluginsStartServices - ); + const factory: ReactEmbeddableFactory< + AnomalyChartsEmbeddableState, + AnomalyChartsEmbeddableState, + AnomalyChartsEmbeddableApi + > = { + type: ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, + deserializeState: (state) => state.rawState, + buildEmbeddable: async (state, buildApi, uuid, parentApi) => { + if (!apiHasExecutionContext(parentApi)) { + throw new Error('Parent API does not have execution context'); + } + const [coreStartServices, pluginsStartServices] = await getStartServices(); + const anomalyChartsDependencies = await getAnomalyChartsServiceDependencies( + coreStartServices, + pluginsStartServices + ); - const [, , mlServices] = anomalyChartsDependencies; + const [, , mlServices] = anomalyChartsDependencies; - const subscriptions = new Subscription(); + const subscriptions = new Subscription(); - const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); - const { - api: timeRangeApi, - comparators: timeRangeComparators, - serialize: serializeTimeRange, - } = initializeTimeRange(state); + const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); + const { + api: timeRangeApi, + comparators: timeRangeComparators, + serialize: serializeTimeRange, + } = initializeTimeRange(state); - const { - anomalyChartsControlsApi, - dataLoadingApi, - serializeAnomalyChartsState, - anomalyChartsComparators, - onAnomalyChartsDestroy, - } = initializeAnomalyChartsControls(state, titlesApi, parentApi); + const { + anomalyChartsControlsApi, + dataLoadingApi, + serializeAnomalyChartsState, + anomalyChartsComparators, + onAnomalyChartsDestroy, + } = initializeAnomalyChartsControls(state, titlesApi, parentApi); - const api = buildApi( - { - isEditingEnabled: () => true, - getTypeDisplayName: () => - i18n.translate('xpack.ml.components.mlAnomalyExplorerEmbeddable.typeDisplayName', { - defaultMessage: 'anomaly charts', - }), - onEdit: async () => { - try { - const { resolveEmbeddableAnomalyChartsUserInput } = await import( - './anomaly_charts_setup_flyout' - ); - const result = await resolveEmbeddableAnomalyChartsUserInput( - coreStartServices, - pluginsStartServices, - parentApi, - uuid, - { - ...serializeTitles(), - ...serializeAnomalyChartsState(), - } - ); - anomalyChartsControlsApi.updateUserInput(result); - } catch (e) { - // eslint-disable-next-line no-console - console.error(e); - return Promise.reject(); - } - }, - ...titlesApi, - ...timeRangeApi, - ...anomalyChartsControlsApi, - ...dataLoadingApi, - dataViews: buildDataViewPublishingApi( - { - anomalyDetectorService: mlServices.anomalyDetectorService, - dataViewsService: pluginsStartServices.data.dataViews, - }, - { jobIds: anomalyChartsControlsApi.jobIds$ }, - subscriptions - ), - serializeState: () => { - return { - rawState: { - timeRange: undefined, + const api = buildApi( + { + isEditingEnabled: () => true, + getTypeDisplayName: () => + i18n.translate('xpack.ml.components.mlAnomalyExplorerEmbeddable.typeDisplayName', { + defaultMessage: 'anomaly charts', + }), + onEdit: async () => { + try { + const { resolveEmbeddableAnomalyChartsUserInput } = await import( + './anomaly_charts_setup_flyout' + ); + const result = await resolveEmbeddableAnomalyChartsUserInput( + coreStartServices, + pluginsStartServices, + parentApi, + uuid, + { ...serializeTitles(), - ...serializeTimeRange(), ...serializeAnomalyChartsState(), - }, - references: [], - }; + } + ); + anomalyChartsControlsApi.updateUserInput(result); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + return Promise.reject(); + } + }, + ...titlesApi, + ...timeRangeApi, + ...anomalyChartsControlsApi, + ...dataLoadingApi, + dataViews: buildDataViewPublishingApi( + { + anomalyDetectorService: mlServices.anomalyDetectorService, + dataViewsService: pluginsStartServices.data.dataViews, }, + { jobIds: anomalyChartsControlsApi.jobIds$ }, + subscriptions + ), + serializeState: () => { + return { + rawState: { + timeRange: undefined, + ...serializeTitles(), + ...serializeTimeRange(), + ...serializeAnomalyChartsState(), + }, + references: [], + }; }, - { - ...timeRangeComparators, - ...titleComparators, - ...anomalyChartsComparators, - } - ); + }, + { + ...timeRangeComparators, + ...titleComparators, + ...anomalyChartsComparators, + } + ); - const appliedTimeRange$: Observable = fetch$(api).pipe( - map((fetchContext) => fetchContext.timeRange), - distinctUntilChanged(fastIsEqual) - ); + const appliedTimeRange$: Observable = fetch$(api).pipe( + map((fetchContext) => fetchContext.timeRange), + distinctUntilChanged(fastIsEqual) + ); - const { onRenderComplete, onLoading, onError } = dataLoadingApi; - const contextServices = { - mlServices: { - ...mlServices, - }, - ...coreStartServices, - ...pluginsStartServices, - }; + const { onRenderComplete, onLoading, onError } = dataLoadingApi; + const contextServices = { + mlServices: { + ...mlServices, + }, + ...coreStartServices, + ...pluginsStartServices, + }; - return { - api, - Component: () => { - if (!apiHasExecutionContext(parentApi)) { - throw new Error('Parent API does not have execution context'); - } + return { + api, + Component: () => { + if (!apiHasExecutionContext(parentApi)) { + throw new Error('Parent API does not have execution context'); + } - useReactEmbeddableExecutionContext( - coreStartServices.executionContext, - parentApi.executionContext, - ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, - uuid - ); + useReactEmbeddableExecutionContext( + coreStartServices.executionContext, + parentApi.executionContext, + ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, + uuid + ); - useUnmount(() => { - onAnomalyChartsDestroy(); - subscriptions.unsubscribe(); - }); - const { euiTheme } = useEuiTheme(); + useUnmount(() => { + onAnomalyChartsDestroy(); + subscriptions.unsubscribe(); + }); + const { euiTheme } = useEuiTheme(); - return ( - - -
- -
-
-
- ); - }, - }; - }, - }; + return ( + + +
+ +
+
+
+ ); + }, + }; + }, + }; return factory; }; diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx index 4765950b341f9..61a2fadeb6df8 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx @@ -97,7 +97,11 @@ describe('getAnomalySwimLaneEmbeddableFactory', () => { >; render( - + maybeId={'maybe_id'} type={ANOMALY_SWIMLANE_EMBEDDABLE_TYPE} onApiAvailable={onApiAvailable} diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx index c67c2ed157cda..6de07c5db851e 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx @@ -89,8 +89,8 @@ export const getAnomalySwimLaneEmbeddableFactory = ( ) => { const factory: ReactEmbeddableFactory< AnomalySwimLaneEmbeddableState, - AnomalySwimLaneEmbeddableApi, - AnomalySwimlaneRuntimeState + AnomalySwimlaneRuntimeState, + AnomalySwimLaneEmbeddableApi > = { type: ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, deserializeState: (state) => state.rawState, diff --git a/x-pack/plugins/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx b/x-pack/plugins/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx index 3fa630d7194e9..dcddb9f2d373e 100644 --- a/x-pack/plugins/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx +++ b/x-pack/plugins/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx @@ -36,8 +36,8 @@ export const getSingleMetricViewerEmbeddableFactory = ( ) => { const factory: ReactEmbeddableFactory< SingleMetricViewerEmbeddableState, - SingleMetricViewerEmbeddableApi, - SingleMetricViewerRuntimeState + SingleMetricViewerRuntimeState, + SingleMetricViewerEmbeddableApi > = { type: ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE, deserializeState: (state) => state.rawState, diff --git a/x-pack/plugins/ml/public/shared_components/anomaly_swim_lane.tsx b/x-pack/plugins/ml/public/shared_components/anomaly_swim_lane.tsx index b7748a753cc5c..5c995d0ddcb65 100644 --- a/x-pack/plugins/ml/public/shared_components/anomaly_swim_lane.tsx +++ b/x-pack/plugins/ml/public/shared_components/anomaly_swim_lane.tsx @@ -116,7 +116,11 @@ export const AnomalySwimLane: FC = ({ ); return ( - + maybeId={id} type={ANOMALY_SWIMLANE_EMBEDDABLE_TYPE} getParentApi={() => parentApi} diff --git a/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_failed_transactions_chart/react_embeddable_factory.tsx b/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_failed_transactions_chart/react_embeddable_factory.tsx index d6f2e43c724b2..6418799c4ad38 100644 --- a/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_failed_transactions_chart/react_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_failed_transactions_chart/react_embeddable_factory.tsx @@ -19,6 +19,7 @@ export const APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE = export const getApmAlertingFailedTransactionsChartEmbeddableFactory = (deps: EmbeddableDeps) => { const factory: ReactEmbeddableFactory< + EmbeddableApmAlertingVizProps, EmbeddableApmAlertingVizProps, DefaultEmbeddableApi > = { diff --git a/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_latency_chart/react_embeddable_factory.tsx b/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_latency_chart/react_embeddable_factory.tsx index f828a35a89d69..0795c821fc465 100644 --- a/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_latency_chart/react_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_latency_chart/react_embeddable_factory.tsx @@ -18,6 +18,7 @@ export const APM_ALERTING_LATENCY_CHART_EMBEDDABLE = 'APM_ALERTING_LATENCY_CHART export const getApmAlertingLatencyChartEmbeddableFactory = (deps: EmbeddableDeps) => { const factory: ReactEmbeddableFactory< + EmbeddableApmAlertingLatencyVizProps, EmbeddableApmAlertingLatencyVizProps, DefaultEmbeddableApi > = { diff --git a/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_throughput_chart/react_embeddable_factory.tsx b/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_throughput_chart/react_embeddable_factory.tsx index 7ce986cd3b5bc..6fe2135d8ec62 100644 --- a/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_throughput_chart/react_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/apm/public/embeddable/alerting/alerting_throughput_chart/react_embeddable_factory.tsx @@ -18,6 +18,7 @@ export const APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE = 'APM_ALERTING_THROUGHPUT export const getApmAlertingThroughputChartEmbeddableFactory = (deps: EmbeddableDeps) => { const factory: ReactEmbeddableFactory< + EmbeddableApmAlertingVizProps, EmbeddableApmAlertingVizProps, DefaultEmbeddableApi > = { diff --git a/x-pack/plugins/observability_solution/infra/public/components/log_stream/log_stream_react_embeddable.tsx b/x-pack/plugins/observability_solution/infra/public/components/log_stream/log_stream_react_embeddable.tsx index 313eb476c4ae5..bbb2e09d8660a 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/log_stream/log_stream_react_embeddable.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/log_stream/log_stream_react_embeddable.tsx @@ -24,7 +24,11 @@ import { useKibanaContextForPluginProvider } from '../../hooks/use_kibana'; import { InfraClientStartDeps, InfraClientStartExports } from '../../types'; export function getLogStreamEmbeddableFactory(services: Services) { - const factory: ReactEmbeddableFactory = { + const factory: ReactEmbeddableFactory< + LogStreamSerializedState, + LogStreamSerializedState, + LogStreamApi + > = { type: LOG_STREAM_EMBEDDABLE, deserializeState: (state) => state.rawState, buildEmbeddable: async (state, buildApi) => { diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx index 7472c43253454..b70e1d8e4c40a 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx @@ -33,7 +33,11 @@ export const getAlertsPanelTitle = () => }); export function getAlertsEmbeddableFactory(deps: SloEmbeddableDeps, kibanaVersion: string) { - const factory: ReactEmbeddableFactory = { + const factory: ReactEmbeddableFactory< + SloAlertsEmbeddableState, + SloAlertsEmbeddableState, + SloAlertsApi + > = { type: SLO_ALERTS_EMBEDDABLE_ID, deserializeState: (state) => { return state.rawState as SloAlertsEmbeddableState; diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx index 63ebb3fb37205..6d01995fb8191 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/error_budget/error_budget_react_embeddable_factory.tsx @@ -28,7 +28,11 @@ export const getErrorBudgetPanelTitle = () => const queryClient = new QueryClient(); export const getErrorBudgetEmbeddableFactory = (deps: SloEmbeddableDeps) => { - const factory: ReactEmbeddableFactory = { + const factory: ReactEmbeddableFactory< + SloErrorBudgetEmbeddableState, + SloErrorBudgetEmbeddableState, + ErrorBudgetApi + > = { type: SLO_ERROR_BUDGET_ID, deserializeState: (state) => { return state.rawState as SloErrorBudgetEmbeddableState; diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx index 33252386c0e81..861909b040e9a 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx @@ -36,7 +36,11 @@ export const getOverviewPanelTitle = () => defaultMessage: 'SLO Overview', }); export const getOverviewEmbeddableFactory = (deps: SloEmbeddableDeps) => { - const factory: ReactEmbeddableFactory = { + const factory: ReactEmbeddableFactory< + SloOverviewEmbeddableState, + SloOverviewEmbeddableState, + SloOverviewApi + > = { type: SLO_OVERVIEW_EMBEDDABLE_ID, deserializeState: (state) => { return state.rawState as SloOverviewEmbeddableState; From c14a56e79a4cfaab4fea59768675b16bd6b24b2d Mon Sep 17 00:00:00 2001 From: Sid Date: Wed, 19 Jun 2024 16:17:41 +0200 Subject: [PATCH 116/127] Upgrade `ws@8.17.0` -> `ws@8.17.1` (#186362) Update ws production dependency to use 8.17.1. WS changelog: https://github.com/websockets/ws/releases/tag/8.17.1 --- yarn.lock | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index d1dec3cae024a..d59f566dc8627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32310,15 +32310,20 @@ write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@8.17.0, ws@>=8.16.0, ws@^8.2.3, ws@^8.4.2, ws@^8.9.0: +ws@8.17.0: version "8.17.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== +ws@>=8.16.0, ws@^8.2.3, ws@^8.4.2, ws@^8.9.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + ws@^7.3.1, ws@^7.4.2: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== x-default-browser@^0.4.0: version "0.4.0" From c2986d9a6f09fd7644695ad72f46e7acfec964a3 Mon Sep 17 00:00:00 2001 From: Alex Szabo Date: Wed, 19 Jun 2024 16:55:18 +0200 Subject: [PATCH 117/127] [CI] Fix missing test failure annotations (#186446) ## Summary rename `SLACK_NOTIFICATIONS_ENABLED` => `ELASTIC_SLACK_NOTIFICATIONS_ENABLED` to follow up on elastic-wide buildkite changes. This should re-enable test failure listing on the slack errors we post. --- .buildkite/pipeline-utils/test-failures/annotate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/pipeline-utils/test-failures/annotate.ts b/.buildkite/pipeline-utils/test-failures/annotate.ts index c49128ae3c62b..39aa2d36b9ddb 100644 --- a/.buildkite/pipeline-utils/test-failures/annotate.ts +++ b/.buildkite/pipeline-utils/test-failures/annotate.ts @@ -177,7 +177,7 @@ export const annotateTestFailures = async () => { ); } - if (process.env.SLACK_NOTIFICATIONS_ENABLED === 'true') { + if (process.env.ELASTIC_SLACK_NOTIFICATIONS_ENABLED === 'true') { buildkite.setMetadata( 'slack:test_failures:body', getSlackMessage(failures, failureHtmlArtifacts) From 39ac3e1ceac31ef8cb52b8842e77103905973d9f Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Wed, 19 Jun 2024 10:59:52 -0400 Subject: [PATCH 118/127] [Fleet] Add retry when retrieving agent version (#186459) --- .../inputs_with_standalone_docker_agent.ts | 3 +-- x-pack/test/fleet_cypress/artifact_manager.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts b/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts index 64a9077b916d9..ca1d8c0c3f312 100644 --- a/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts +++ b/x-pack/test/fleet_api_integration/apis/integrations/inputs_with_standalone_docker_agent.ts @@ -25,8 +25,7 @@ export default function (providerContext: FtrProviderContext) { const config = getService('config'); const log = getService('log'); - // FLAKY: https://github.com/elastic/kibana/issues/184681 - describe.skip('inputs_with_standalone_docker_agent', () => { + describe('inputs_with_standalone_docker_agent', () => { skipIfNoDockerRegistry(providerContext); let apiKey: string; let agent: AgentProcess; diff --git a/x-pack/test/fleet_cypress/artifact_manager.ts b/x-pack/test/fleet_cypress/artifact_manager.ts index 17ba9b0a5517d..0fe6609f28efc 100644 --- a/x-pack/test/fleet_cypress/artifact_manager.ts +++ b/x-pack/test/fleet_cypress/artifact_manager.ts @@ -7,8 +7,14 @@ import axios from 'axios'; import { last } from 'lodash'; +import pRetry from 'p-retry'; + +const DEFAULT_VERSION = '8.15.0-SNAPSHOT'; export async function getLatestVersion(): Promise { - const response: any = await axios('https://artifacts-api.elastic.co/v1/versions'); - return last(response.data.versions as string[]) || '8.1.0-SNAPSHOT'; + return pRetry(() => axios('https://artifacts-api.elastic.co/v1/versions'), { + maxRetryTime: 60 * 1000, // 1 minute + }) + .then((response) => last(response.data.versions as string[]) || DEFAULT_VERSION) + .catch(() => DEFAULT_VERSION); } From 6e905c24dde2dff938f3a9cdc7e17b7455e3a081 Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Wed, 19 Jun 2024 17:05:51 +0200 Subject: [PATCH 119/127] [Fleet] Adjust delete package policy warning for multiple agent policies (#186316) Fixes https://github.com/elastic/kibana/issues/182218 ## Summary Add a warning to integration policy delete action in case of multiple agent policies. ![Screenshot 2024-06-19 at 10 17 52](https://github.com/elastic/kibana/assets/16084106/dacca9f8-afd1-4290-bf6e-ea8cb468a5b7) ![Screenshot 2024-06-19 at 10 17 56](https://github.com/elastic/kibana/assets/16084106/6c2322c1-e9a6-4028-9ea4-e84659445e19) ## Testing - Enable `enableReusableIntegrationPolicies` - Get an integration that has multiple agent policies and navigate to `integrations/detail/{pkgName-Version}/policies` - From the actions on the rigth, select `Delete integration` - A warning with `This integration is shared by multiple agent policies.` should be displayed ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../package_policies_table.tsx | 2 +- .../detail/policies/package_policies.tsx | 2 +- .../package_policy_actions_menu.test.tsx | 137 ++++++++++-------- .../package_policy_actions_menu.tsx | 7 +- .../package_policy_delete_provider.tsx | 100 +++++++++---- 5 files changed, 155 insertions(+), 93 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx index fd9a27ed66f01..a121c797757d7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx @@ -249,7 +249,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ render: (packagePolicy: InMemoryPackagePolicy) => { return canWriteIntegrationPolicies ? ( = {}): AgentPolicy { - return { - id: 'some-uuid1', - namespace: 'default', - monitoring_enabled: [], - name: 'Test Policy', - description: '', - is_preconfigured: false, - status: 'active', - is_managed: false, - revision: 1, - updated_at: '', - updated_by: 'elastic', - package_policies: [], - is_protected: false, - ...props, - }; +function createMockAgentPolicies(props: Partial = {}): AgentPolicy[] { + return [ + { + id: 'some-uuid1', + namespace: 'default', + monitoring_enabled: [], + name: 'Test Policy', + description: '', + is_preconfigured: false, + status: 'active', + is_managed: false, + revision: 1, + updated_at: '', + updated_by: 'elastic', + package_policies: [], + is_protected: false, + ...props, + }, + ]; } function createMockPackagePolicy( @@ -81,60 +85,67 @@ function createMockPackagePolicy( ...props, }; } +describe('PackagePolicyActionsMenu', () => { + beforeAll(() => { + jest.spyOn(ExperimentalFeaturesService, 'get').mockReturnValue({ + enableReusableIntegrationPolicies: false, + } as any); + }); -test('Should disable upgrade button if package does not have upgrade', async () => { - const agentPolicy = createMockAgentPolicy(); - const packagePolicy = createMockPackagePolicy({ hasUpgrade: false }); - const { utils } = renderMenu({ agentPolicy, packagePolicy }); - await act(async () => { - const upgradeButton = utils.getByText('Upgrade integration policy').closest('button'); - expect(upgradeButton).toBeDisabled(); + it('Should disable upgrade button if package does not have upgrade', async () => { + const agentPolicies = createMockAgentPolicies(); + const packagePolicy = createMockPackagePolicy({ hasUpgrade: false }); + const { utils } = renderMenu({ agentPolicies, packagePolicy }); + await act(async () => { + const upgradeButton = utils.getByText('Upgrade integration policy').closest('button'); + expect(upgradeButton).toBeDisabled(); + }); }); -}); -test('Should enable upgrade button if package has upgrade', async () => { - const agentPolicy = createMockAgentPolicy(); - const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); - const { utils } = renderMenu({ agentPolicy, packagePolicy }); + it('Should enable upgrade button if package has upgrade', async () => { + const agentPolicies = createMockAgentPolicies(); + const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); + const { utils } = renderMenu({ agentPolicies, packagePolicy }); - await act(async () => { - const upgradeButton = utils.getByTestId('PackagePolicyActionsUpgradeItem'); - expect(upgradeButton).not.toBeDisabled(); + await act(async () => { + const upgradeButton = utils.getByTestId('PackagePolicyActionsUpgradeItem'); + expect(upgradeButton).not.toBeDisabled(); + }); }); -}); -test('Should not be able to delete integration from a managed policy', async () => { - const agentPolicy = createMockAgentPolicy({ is_managed: true }); - const packagePolicy = createMockPackagePolicy(); - const { utils } = renderMenu({ agentPolicy, packagePolicy }); - await act(async () => { - expect(utils.queryByText('Delete integration')).toBeNull(); + it('Should not be able to delete integration from a managed policy', async () => { + const agentPolicies = createMockAgentPolicies({ is_managed: true }); + const packagePolicy = createMockPackagePolicy(); + const { utils } = renderMenu({ agentPolicies, packagePolicy }); + await act(async () => { + expect(utils.queryByText('Delete integration')).toBeNull(); + }); }); -}); -test('Should be able to delete integration from a non-managed policy', async () => { - const agentPolicy = createMockAgentPolicy({ is_managed: false }); - const packagePolicy = createMockPackagePolicy(); - const { utils } = renderMenu({ agentPolicy, packagePolicy }); - await act(async () => { - expect(utils.queryByText('Delete integration')).not.toBeNull(); + it('Should be able to delete integration from a non-managed policy', async () => { + const agentPolicies = createMockAgentPolicies({ is_managed: false }); + const packagePolicy = createMockPackagePolicy(); + const { utils } = renderMenu({ agentPolicies, packagePolicy }); + await act(async () => { + expect(utils.queryByText('Delete integration')).not.toBeNull(); + }); }); -}); -test('Should show add button if the policy is not managed and showAddAgent=true', async () => { - const agentPolicy = createMockAgentPolicy(); - const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); - const { utils } = renderMenu({ agentPolicy, packagePolicy, showAddAgent: true }); - await act(async () => { - expect(utils.queryByText('Add agent')).not.toBeNull(); + it('Should show add button if the policy is not managed and showAddAgent=true', async () => { + const agentPolicies = createMockAgentPolicies(); + const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); + const { utils } = renderMenu({ agentPolicies, packagePolicy, showAddAgent: true }); + await act(async () => { + expect(utils.queryByText('Add agent')).not.toBeNull(); + }); }); -}); -test('Should not show add button if the policy is managed and showAddAgent=true', async () => { - const agentPolicy = createMockAgentPolicy({ is_managed: true }); - const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); - const { utils } = renderMenu({ agentPolicy, packagePolicy, showAddAgent: true }); - await act(async () => { - expect(utils.queryByText('Add agent')).toBeNull(); + it('Should not show add button if the policy is managed and showAddAgent=true', async () => { + const agentPolicies = createMockAgentPolicies({ is_managed: true }); + const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); + const { utils } = renderMenu({ agentPolicies, packagePolicy, showAddAgent: true }); + await act(async () => { + expect(utils.queryByText('Add agent')).toBeNull(); + }); }); }); diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx index 23ae673ad892a..a8839e23a99f9 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx @@ -19,14 +19,14 @@ import { DangerEuiContextMenuItem } from './danger_eui_context_menu_item'; import { PackagePolicyDeleteProvider } from './package_policy_delete_provider'; export const PackagePolicyActionsMenu: React.FunctionComponent<{ - agentPolicy?: AgentPolicy; + agentPolicies: AgentPolicy[]; packagePolicy: InMemoryPackagePolicy; showAddAgent?: boolean; defaultIsOpen?: boolean; upgradePackagePolicyHref?: string; from?: 'fleet-policy-list' | undefined; }> = ({ - agentPolicy, + agentPolicies, packagePolicy, showAddAgent, upgradePackagePolicyHref, @@ -37,6 +37,7 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ const { getHref } = useLink(); const authz = useAuthz(); + const agentPolicy = agentPolicies.length > 0 ? agentPolicies[0] : undefined; // TODO: handle multiple agent policies const canWriteIntegrationPolicies = authz.integrations.writeIntegrationPolicies; const isFleetServerPolicy = agentPolicy && policyHasFleetServer(agentPolicy); @@ -126,7 +127,7 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ ? DangerEuiContextMenuItem : EuiContextMenuItem; menuItems.push( - + {(deletePackagePoliciesPrompt) => { return ( React.ReactElement; } @@ -27,7 +29,7 @@ export type DeletePackagePoliciesPrompt = ( type OnSuccessCallback = (packagePoliciesDeleted: string[]) => void; export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ - agentPolicy, + agentPolicies, children, }) => { const { notifications } = useStartServices(); @@ -40,27 +42,30 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ const [agentsCount, setAgentsCount] = useState(0); const [isLoading, setIsLoading] = useState(false); const onSuccessCallback = useRef(null); + const { enableReusableIntegrationPolicies } = ExperimentalFeaturesService.get(); + + const hasMultipleAgentPolicies = + enableReusableIntegrationPolicies && agentPolicies && agentPolicies.length > 1; const fetchAgentsCount = useMemo( () => async () => { - if (isLoadingAgentsCount || !isFleetEnabled || !agentPolicy) { + if (isLoadingAgentsCount || !isFleetEnabled || !agentPolicies) { return; } setIsLoadingAgentsCount(true); - const { data } = await sendRequest<{ total: number }>({ - path: AGENT_API_ROUTES.LIST_PATTERN, - method: 'get', - query: { - page: 1, - perPage: 1, - kuery: `${AGENTS_PREFIX}.policy_id : ${agentPolicy.id}`, - }, - version: API_VERSIONS.public.v1, + + const kuery = `(${agentPolicies + .map((policy) => `${AGENTS_PREFIX}.policy_id:"${policy.id}"`) + .join(' or ')})`; + + const request = await sendGetAgents({ + kuery, + showInactive: false, }); - setAgentsCount(data?.total || 0); + setAgentsCount(request.data?.total || 0); setIsLoadingAgentsCount(false); }, - [agentPolicy, isFleetEnabled, isLoadingAgentsCount] + [agentPolicies, isFleetEnabled, isLoadingAgentsCount] ); const deletePackagePoliciesPrompt = useMemo( @@ -87,6 +92,11 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ [] ); + const agentPoliciesNamesList = useMemo( + () => agentPolicies?.map((p) => p.name).join(', '), + [agentPolicies] + ); + const deletePackagePolicies = useMemo( () => async () => { setIsLoading(true); @@ -185,8 +195,23 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ id="xpack.fleet.deletePackagePolicy.confirmModal.loadingAgentsCountMessage" defaultMessage="Checking affected agents…" /> - ) : agentsCount ? ( + ) : agentsCount && agentPolicies ? ( <> + {hasMultipleAgentPolicies && ( + <> + + } + /> + + + )} = ({ /> } > - {agentPolicy?.name}, - }} - /> + {hasMultipleAgentPolicies ? ( + + } + position="top" + /> + ), + }} + /> + ) : ( + {agentPolicies[0]?.name}, + }} + /> + )} From 37ca5c6bd952378b96beb5974bc557da718682b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Wed, 19 Jun 2024 16:18:13 +0100 Subject: [PATCH 120/127] [Spaces] Add solution view select in UI (#186178) --- .buildkite/ftr_configs.yml | 1 + x-pack/plugins/spaces/kibana.jsonc | 3 +- x-pack/plugins/spaces/public/constants.ts | 2 + .../customize_space.test.tsx.snap | 1 + .../customize_space/customize_space.tsx | 2 +- .../edit_space/manage_space_page.test.tsx | 90 ++++++++++- .../edit_space/manage_space_page.tsx | 54 +++++-- .../section_panel/section_panel.tsx | 3 +- .../edit_space/solution_view/index.ts | 8 + .../solution_view/solution_view.tsx | 153 ++++++++++++++++++ .../management/spaces_management_app.test.tsx | 4 +- .../management/spaces_management_app.tsx | 26 ++- x-pack/plugins/spaces/public/plugin.tsx | 5 + x-pack/plugins/spaces/tsconfig.json | 1 + .../apps/spaces/create_edit_space.ts | 36 +++++ x-pack/test/functional/apps/spaces/index.ts | 1 + .../solution_view_flag_enabled/config.ts | 31 ++++ .../create_edit_space.ts | 69 ++++++++ .../solution_view_flag_enabled/index.ts | 14 ++ .../page_objects/space_selector_page.ts | 21 +++ 20 files changed, 506 insertions(+), 19 deletions(-) create mode 100644 x-pack/plugins/spaces/public/management/edit_space/solution_view/index.ts create mode 100644 x-pack/plugins/spaces/public/management/edit_space/solution_view/solution_view.tsx create mode 100644 x-pack/test/functional/apps/spaces/create_edit_space.ts create mode 100644 x-pack/test/functional/apps/spaces/solution_view_flag_enabled/config.ts create mode 100644 x-pack/test/functional/apps/spaces/solution_view_flag_enabled/create_edit_space.ts create mode 100644 x-pack/test/functional/apps/spaces/solution_view_flag_enabled/index.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 83ae94ada8d06..c12bcf333dc08 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -326,6 +326,7 @@ enabled: - x-pack/test/functional/apps/search_playground/config.ts - x-pack/test/functional/apps/snapshot_restore/config.ts - x-pack/test/functional/apps/spaces/config.ts + - x-pack/test/functional/apps/spaces/solution_view_flag_enabled/config.ts - x-pack/test/functional/apps/status_page/config.ts - x-pack/test/functional/apps/transform/creation/index_pattern/config.ts - x-pack/test/functional/apps/transform/creation/runtime_mappings_saved_search/config.ts diff --git a/x-pack/plugins/spaces/kibana.jsonc b/x-pack/plugins/spaces/kibana.jsonc index 3b1555b52fcfd..3c32314168417 100644 --- a/x-pack/plugins/spaces/kibana.jsonc +++ b/x-pack/plugins/spaces/kibana.jsonc @@ -19,7 +19,8 @@ "home", "management", "usageCollection", - "cloud" + "cloud", + "cloudExperiments" ], "requiredBundles": [ "esUiShared", diff --git a/x-pack/plugins/spaces/public/constants.ts b/x-pack/plugins/spaces/public/constants.ts index 64781228d4f43..27c6f04225d4f 100644 --- a/x-pack/plugins/spaces/public/constants.ts +++ b/x-pack/plugins/spaces/public/constants.ts @@ -22,3 +22,5 @@ export const getSpacesFeatureDescription = () => { export const DEFAULT_OBJECT_NOUN = i18n.translate('xpack.spaces.shareToSpace.objectNoun', { defaultMessage: 'object', }); + +export const SOLUTION_NAV_FEATURE_FLAG_NAME = 'solutionNavEnabled'; diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap index c799b56e7f7ae..31de1c9ea55e9 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap @@ -2,6 +2,7 @@ exports[`renders correctly 1`] = ` { }); return ( - + diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx index c95e4e4363dee..68e8421449cf8 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx @@ -10,12 +10,13 @@ import { EuiButton } from '@elastic/eui'; import { waitFor } from '@testing-library/react'; import type { ReactWrapper } from 'enzyme'; import React from 'react'; +import { of } from 'rxjs'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; import { notificationServiceMock, scopedHistoryMock } from '@kbn/core/public/mocks'; import { KibanaFeature } from '@kbn/features-plugin/public'; import { featuresPluginMock } from '@kbn/features-plugin/public/mocks'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { ConfirmAlterActiveSpaceModal } from './confirm_alter_active_space_modal'; import { EnabledFeatures } from './enabled_features'; @@ -105,6 +106,93 @@ describe('ManageSpacePage', () => { }); }); + it('shows solution view select when enabled', async () => { + const spacesManager = spacesManagerMock.create(); + spacesManager.createSpace = jest.fn(spacesManager.createSpace); + spacesManager.getActiveSpace = jest.fn().mockResolvedValue(space); + + const wrapper = mountWithIntl( + + ); + + await waitFor(() => { + wrapper.update(); + expect(wrapper.find('input[name="name"]')).toHaveLength(1); + }); + + expect(findTestSubject(wrapper, 'navigationPanel')).toHaveLength(1); + }); + + it('hides solution view select when not enabled or undefined', async () => { + const spacesManager = spacesManagerMock.create(); + spacesManager.createSpace = jest.fn(spacesManager.createSpace); + spacesManager.getActiveSpace = jest.fn().mockResolvedValue(space); + + { + const wrapper = mountWithIntl( + + ); + + await waitFor(() => { + wrapper.update(); + expect(wrapper.find('input[name="name"]')).toHaveLength(1); + }); + + expect(findTestSubject(wrapper, 'navigationPanel')).toHaveLength(0); + } + + { + const wrapper = mountWithIntl( + + ); + + await waitFor(() => { + wrapper.update(); + expect(wrapper.find('input[name="name"]')).toHaveLength(1); + }); + + expect(findTestSubject(wrapper, 'navigationPanel')).toHaveLength(0); + } + }); + it('shows feature visibility controls when allowed', async () => { const spacesManager = spacesManagerMock.create(); spacesManager.createSpace = jest.fn(spacesManager.createSpace); diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx index fbba203f8e060..8ea38d4fcc316 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import { difference } from 'lodash'; import React, { Component } from 'react'; +import type { Observable, Subscription } from 'rxjs'; import type { Capabilities, NotificationsStart, ScopedHistory } from '@kbn/core/public'; import { SectionLoading } from '@kbn/es-ui-shared-plugin/public'; @@ -29,6 +30,7 @@ import { ConfirmAlterActiveSpaceModal } from './confirm_alter_active_space_modal import { CustomizeSpace } from './customize_space'; import { DeleteSpacesButton } from './delete_spaces_button'; import { EnabledFeatures } from './enabled_features'; +import { SolutionView } from './solution_view'; import type { Space } from '../../../common'; import { isReservedSpace } from '../../../common'; import { getSpacesFeatureDescription } from '../../constants'; @@ -54,6 +56,7 @@ interface Props { capabilities: Capabilities; history: ScopedHistory; allowFeatureVisibility: boolean; + isSolutionNavEnabled$?: Observable; } interface State { @@ -67,10 +70,13 @@ interface State { isInvalid: boolean; error?: string; }; + isSolutionNavEnabled: boolean; } export class ManageSpacePage extends Component { private readonly validator: SpaceValidator; + private initialSpaceState: State['space'] | null = null; + private subscription: Subscription | null = null; constructor(props: Props) { super(props); @@ -83,6 +89,7 @@ export class ManageSpacePage extends Component { color: getSpaceColor({}), }, features: [], + isSolutionNavEnabled: false, }; } @@ -107,6 +114,12 @@ export class ManageSpacePage extends Component { }), }); } + + if (this.props.isSolutionNavEnabled$) { + this.subscription = this.props.isSolutionNavEnabled$.subscribe((isEnabled) => { + this.setState({ isSolutionNavEnabled: isEnabled }); + }); + } } public async componentDidUpdate(previousProps: Props) { @@ -115,6 +128,12 @@ export class ManageSpacePage extends Component { } } + public componentWillUnmount() { + if (this.subscription) { + this.subscription.unsubscribe(); + } + } + public render() { if (!this.props.capabilities.spaces.manage) { return ( @@ -161,6 +180,13 @@ export class ManageSpacePage extends Component { validator={this.validator} /> + {this.state.isSolutionNavEnabled && ( + <> + + + + )} + {this.props.allowFeatureVisibility && ( <> @@ -298,8 +324,10 @@ export class ManageSpacePage extends Component { const haveDisabledFeaturesChanged = space.disabledFeatures.length !== originalSpace.disabledFeatures.length || difference(space.disabledFeatures, originalSpace.disabledFeatures).length > 0; + const hasSolutionViewChanged = + this.state.space.solution !== this.initialSpaceState?.solution; - if (editingActiveSpace && haveDisabledFeaturesChanged) { + if (editingActiveSpace && (haveDisabledFeaturesChanged || hasSolutionViewChanged)) { this.setState({ showAlteringActiveSpaceDialog: true, }); @@ -326,17 +354,19 @@ export class ManageSpacePage extends Component { onLoadSpace(space); } + this.initialSpaceState = { + ...space, + avatarType: space.imageUrl ? 'image' : 'initials', + initials: space.initials || getSpaceInitials(space), + color: space.color || getSpaceColor(space), + customIdentifier: false, + customAvatarInitials: + !!space.initials && getSpaceInitials({ name: space.name }) !== space.initials, + customAvatarColor: !!space.color && getSpaceColor({ name: space.name }) !== space.color, + }; + this.setState({ - space: { - ...space, - avatarType: space.imageUrl ? 'image' : 'initials', - initials: space.initials || getSpaceInitials(space), - color: space.color || getSpaceColor(space), - customIdentifier: false, - customAvatarInitials: - !!space.initials && getSpaceInitials({ name: space.name }) !== space.initials, - customAvatarColor: !!space.color && getSpaceColor({ name: space.name }) !== space.color, - }, + space: { ...this.initialSpaceState }, features, originalSpace: space, isLoading: false, @@ -369,6 +399,7 @@ export class ManageSpacePage extends Component { disabledFeatures = [], imageUrl, avatarType, + solution, } = this.state.space; const params = { @@ -379,6 +410,7 @@ export class ManageSpacePage extends Component { color: color ? hsvToHex(hexToHsv(color)).toUpperCase() : color, // Convert 3 digit hex codes to 6 digits since Spaces API requires 6 digits disabledFeatures, imageUrl: avatarType === 'image' ? imageUrl : '', + solution, }; let action; diff --git a/x-pack/plugins/spaces/public/management/edit_space/section_panel/section_panel.tsx b/x-pack/plugins/spaces/public/management/edit_space/section_panel/section_panel.tsx index 4ffa5ae9de2ea..3d07aaabfd6b3 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/section_panel/section_panel.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/section_panel/section_panel.tsx @@ -13,12 +13,13 @@ import React, { Component, Fragment } from 'react'; interface Props { iconType?: IconType; title: string | ReactNode; + dataTestSubj?: string; } export class SectionPanel extends Component { public render() { return ( - + {this.getTitle()} {this.getForm()} diff --git a/x-pack/plugins/spaces/public/management/edit_space/solution_view/index.ts b/x-pack/plugins/spaces/public/management/edit_space/solution_view/index.ts new file mode 100644 index 0000000000000..0aabb34537273 --- /dev/null +++ b/x-pack/plugins/spaces/public/management/edit_space/solution_view/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { SolutionView } from './solution_view'; diff --git a/x-pack/plugins/spaces/public/management/edit_space/solution_view/solution_view.tsx b/x-pack/plugins/spaces/public/management/edit_space/solution_view/solution_view.tsx new file mode 100644 index 0000000000000..0a6dc317161f2 --- /dev/null +++ b/x-pack/plugins/spaces/public/management/edit_space/solution_view/solution_view.tsx @@ -0,0 +1,153 @@ +/* + * Copyright 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 { EuiSuperSelectOption, EuiThemeComputed } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiIcon, + EuiSpacer, + EuiSuperSelect, + EuiText, + EuiTitle, + useEuiTheme, +} from '@elastic/eui'; +import type { FunctionComponent } from 'react'; +import React from 'react'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { Space } from '../../../../common'; +import { SectionPanel } from '../section_panel'; + +type SolutionView = Space['solution']; + +const getOptions = ({ size }: EuiThemeComputed): Array> => { + const iconCss = { marginRight: size.m }; + + return [ + { + value: 'es', + inputDisplay: ( + <> + + {i18n.translate( + 'xpack.spaces.management.manageSpacePage.solutionViewSelect.searchOptionLabel', + { + defaultMessage: 'Search', + } + )} + + ), + 'data-test-subj': 'solutionViewEsOption', + }, + { + value: 'oblt', + inputDisplay: ( + <> + + {i18n.translate( + 'xpack.spaces.management.manageSpacePage.solutionViewSelect.obltOptionLabel', + { + defaultMessage: 'Observability', + } + )} + + ), + 'data-test-subj': 'solutionViewObltOption', + }, + { + value: 'security', + inputDisplay: ( + <> + + {i18n.translate( + 'xpack.spaces.management.manageSpacePage.solutionViewSelect.securityOptionLabel', + { + defaultMessage: 'Security', + } + )} + + ), + 'data-test-subj': 'solutionViewSecurityOption', + }, + { + value: 'classic', + inputDisplay: ( + <> + + {i18n.translate( + 'xpack.spaces.management.manageSpacePage.solutionViewSelect.classicOptionLabel', + { + defaultMessage: 'Classic', + } + )} + + ), + 'data-test-subj': 'solutionViewClassicOption', + }, + ]; +}; + +interface Props { + space: Partial; + onChange: (space: Partial) => void; +} + +export const SolutionView: FunctionComponent = ({ space, onChange }) => { + const { euiTheme } = useEuiTheme(); + + return ( + + + + +

+ +

+
+ + +

+ +

+
+
+ + + { + onChange({ ...space, solution }); + }} + /> + + +
+
+ ); +}; diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index 89e1fc01d493e..b29d13bbd51a2 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -125,7 +125,7 @@ describe('spacesManagementApp', () => { css="You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop)." data-test-subj="kbnRedirectAppLink" > - Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/create","search":"","hash":""}},"allowFeatureVisibility":true} + Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/create","search":"","hash":""}},"allowFeatureVisibility":true,"isSolutionNavEnabled$":{}}
`); @@ -158,7 +158,7 @@ describe('spacesManagementApp', () => { css="You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop)." data-test-subj="kbnRedirectAppLink" > - Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{}},"spaceId":"some-space","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/some-space","search":"","hash":""}},"allowFeatureVisibility":true} + Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{}},"spaceId":"some-space","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/some-space","search":"","hash":""}},"allowFeatureVisibility":true,"isSolutionNavEnabled$":{}} `); diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index fe6776b33f920..eafefd93f4464 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { useParams } from 'react-router-dom'; +import { from, of, shareReplay } from 'rxjs'; import type { StartServicesAccessor } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; @@ -20,6 +21,7 @@ import { Route, Router, Routes } from '@kbn/shared-ux-router'; import type { Space } from '../../common'; import type { ConfigType } from '../config'; +import { SOLUTION_NAV_FEATURE_FLAG_NAME } from '../constants'; import type { PluginsStart } from '../plugin'; import type { SpacesManager } from '../spaces_manager'; @@ -43,8 +45,15 @@ export const spacesManagementApp = Object.freeze({ title, async mount({ element, setBreadcrumbs, history }) { - const [[coreStart, { features }], { SpacesGridPage }, { ManageSpacePage }] = - await Promise.all([getStartServices(), import('./spaces_grid'), import('./edit_space')]); + const [ + [coreStart, { features, cloud, cloudExperiments }], + { SpacesGridPage }, + { ManageSpacePage }, + ] = await Promise.all([ + getStartServices(), + import('./spaces_grid'), + import('./edit_space'), + ]); const spacesFirstBreadcrumb = { text: title, @@ -54,6 +63,17 @@ export const spacesManagementApp = Object.freeze({ chrome.docTitle.change(title); + const onCloud = Boolean(cloud?.isCloudEnabled); + const isSolutionNavEnabled$ = + // Only available on Cloud and if the Launch Darkly flag is turned on + onCloud && cloudExperiments + ? from( + cloudExperiments + .getVariation(SOLUTION_NAV_FEATURE_FLAG_NAME, false) + .catch(() => false) + ).pipe(shareReplay(1)) + : of(false); + const SpacesGridPageWithBreadcrumbs = () => { setBreadcrumbs([{ ...spacesFirstBreadcrumb, href: undefined }]); return ( @@ -87,6 +107,7 @@ export const spacesManagementApp = Object.freeze({ spacesManager={spacesManager} history={history} allowFeatureVisibility={config.allowFeatureVisibility} + isSolutionNavEnabled$={isSolutionNavEnabled$} /> ); }; @@ -113,6 +134,7 @@ export const spacesManagementApp = Object.freeze({ onLoadSpace={onLoadSpace} history={history} allowFeatureVisibility={config.allowFeatureVisibility} + isSolutionNavEnabled$={isSolutionNavEnabled$} /> ); }; diff --git a/x-pack/plugins/spaces/public/plugin.tsx b/x-pack/plugins/spaces/public/plugin.tsx index 14d816739b4c9..01e9eacaddaea 100644 --- a/x-pack/plugins/spaces/public/plugin.tsx +++ b/x-pack/plugins/spaces/public/plugin.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import type { CloudExperimentsPluginStart } from '@kbn/cloud-experiments-plugin/common'; +import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public'; import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; import type { FeaturesPluginStart } from '@kbn/features-plugin/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; @@ -23,11 +25,14 @@ import { getUiApi } from './ui_api'; export interface PluginsSetup { home?: HomePublicPluginSetup; management?: ManagementSetup; + cloud?: CloudSetup; } export interface PluginsStart { features: FeaturesPluginStart; management?: ManagementStart; + cloud?: CloudStart; + cloudExperiments?: CloudExperimentsPluginStart; } /** diff --git a/x-pack/plugins/spaces/tsconfig.json b/x-pack/plugins/spaces/tsconfig.json index b0da959cc57ea..9f79252873307 100644 --- a/x-pack/plugins/spaces/tsconfig.json +++ b/x-pack/plugins/spaces/tsconfig.json @@ -37,6 +37,7 @@ "@kbn/utility-types-jest", "@kbn/security-plugin-types-public", "@kbn/cloud-plugin", + "@kbn/cloud-experiments-plugin", ], "exclude": [ "target/**/*", diff --git a/x-pack/test/functional/apps/spaces/create_edit_space.ts b/x-pack/test/functional/apps/spaces/create_edit_space.ts new file mode 100644 index 0000000000000..cfffc752cca0c --- /dev/null +++ b/x-pack/test/functional/apps/spaces/create_edit_space.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['common', 'settings', 'security', 'spaceSelector']); + const testSubjects = getService('testSubjects'); + + describe('edit space', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + describe('solution view', () => { + it('does not show solution view panel', async () => { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/default', { + shouldUseHashForSubUrl: false, + }); + + await testSubjects.existOrFail('spaces-edit-page'); + await testSubjects.existOrFail('spaces-edit-page > generalPanel'); + await testSubjects.missingOrFail('spaces-edit-page > navigationPanel'); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/spaces/index.ts b/x-pack/test/functional/apps/spaces/index.ts index c951609d6a33f..aa034f4be012b 100644 --- a/x-pack/test/functional/apps/spaces/index.ts +++ b/x-pack/test/functional/apps/spaces/index.ts @@ -13,5 +13,6 @@ export default function spacesApp({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./feature_controls/spaces_security')); loadTestFile(require.resolve('./spaces_selection')); loadTestFile(require.resolve('./enter_space')); + loadTestFile(require.resolve('./create_edit_space')); }); } diff --git a/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/config.ts b/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/config.ts new file mode 100644 index 0000000000000..0d286f5ffa621 --- /dev/null +++ b/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/config.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + '--xpack.cloud_integrations.experiments.enabled=true', + '--xpack.cloud_integrations.experiments.launch_darkly.sdk_key=a_string', + '--xpack.cloud_integrations.experiments.launch_darkly.client_id=a_string', + '--xpack.cloud_integrations.experiments.flag_overrides.solutionNavEnabled=true', + // Note: the base64 string in the cloud.id config contains the ES endpoint required in the functional tests + '--xpack.cloud.id=ftr_fake_cloud_id:aGVsbG8uY29tOjQ0MyRFUzEyM2FiYyRrYm4xMjNhYmM=', + '--xpack.cloud.base_url=https://cloud.elastic.co', + '--xpack.cloud.deployment_url=/deployments/deploymentId', + ], + }, + }; +} diff --git a/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/create_edit_space.ts b/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/create_edit_space.ts new file mode 100644 index 0000000000000..b6b5eff6ef5f2 --- /dev/null +++ b/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/create_edit_space.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['common', 'settings', 'security', 'spaceSelector']); + const testSubjects = getService('testSubjects'); + const find = getService('find'); + + describe('edit space', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + describe('solution view', () => { + it('does show the solution view panel', async () => { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/default', { + shouldUseHashForSubUrl: false, + }); + + await testSubjects.existOrFail('spaces-edit-page'); + await testSubjects.existOrFail('spaces-edit-page > generalPanel'); + await testSubjects.existOrFail('spaces-edit-page > navigationPanel'); + }); + + it('changes the space solution and updates the side navigation', async () => { + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/default', { + shouldUseHashForSubUrl: false, + }); + + // Make sure we are on the classic side nav + await testSubjects.existOrFail('mgtSideBarNav'); + await testSubjects.missingOrFail('searchSideNav'); + + // change to Enterprise Search + await PageObjects.spaceSelector.changeSolutionView('es'); + await PageObjects.spaceSelector.clickSaveSpaceCreation(); + await PageObjects.spaceSelector.confirmModal(); + + await find.waitForDeletedByCssSelector('.kibanaWelcomeLogo'); + + // Search side nav is loaded + await testSubjects.existOrFail('searchSideNav'); + await testSubjects.missingOrFail('mgtSideBarNav'); + + // change back to classic + await PageObjects.common.navigateToUrl('management', 'kibana/spaces/edit/default', { + shouldUseHashForSubUrl: false, + }); + await PageObjects.spaceSelector.changeSolutionView('classic'); + await PageObjects.spaceSelector.clickSaveSpaceCreation(); + await PageObjects.spaceSelector.confirmModal(); + + await testSubjects.existOrFail('mgtSideBarNav'); + await testSubjects.missingOrFail('searchSideNav'); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/index.ts b/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/index.ts new file mode 100644 index 0000000000000..99ce8f2ab16e7 --- /dev/null +++ b/x-pack/test/functional/apps/spaces/solution_view_flag_enabled/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function spacesApp({ loadTestFile }: FtrProviderContext) { + describe('Spaces app (with solution view)', function spacesAppTestSuite() { + loadTestFile(require.resolve('./create_edit_space')); + }); +} diff --git a/x-pack/test/functional/page_objects/space_selector_page.ts b/x-pack/test/functional/page_objects/space_selector_page.ts index 8c56dee81f435..a9bea52bcd2e8 100644 --- a/x-pack/test/functional/page_objects/space_selector_page.ts +++ b/x-pack/test/functional/page_objects/space_selector_page.ts @@ -120,6 +120,22 @@ export class SpaceSelectorPageObject extends FtrService { await this.testSubjects.setValue('euiColorPickerAnchor', hexValue); } + async openSolutionViewSelect() { + const solutionViewSelect = await this.testSubjects.find('solutionViewSelect'); + const classes = await solutionViewSelect.getAttribute('class'); + + const isOpen = classes?.includes('isOpen') ?? false; + if (!isOpen) { + await solutionViewSelect.click(); + } + } + + async changeSolutionView(solution: 'es' | 'oblt' | 'security' | 'classic') { + await this.openSolutionViewSelect(); + const serialized = solution.charAt(0).toUpperCase() + solution.slice(1); + await this.testSubjects.click(`solutionView${serialized}Option`); + } + async clickShowFeatures() { await this.testSubjects.click('show-hide-section-link'); } @@ -208,6 +224,11 @@ export class SpaceSelectorPageObject extends FtrService { await this.testSubjects.click('confirmModalConfirmButton'); } + // Generic for any confirm modal + async confirmModal() { + await this.testSubjects.click('confirmModalConfirmButton'); + } + async clickOnSpaceb() { await this.testSubjects.click('space-avatar-space_b'); } From 5e346b2561d36efc6e0cd661027e2111474f6232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:37:04 +0200 Subject: [PATCH 121/127] [Console] Enable monaco by default (#184862) ## Summary Closes https://github.com/elastic/kibana/issues/184025 This PR enables the migration from Ace to Monaco in Dev Tools Console by default in the main branch. All serverless projects will still have the migration disabled by default. After 8.15 is branched, the migration will be disabled there as well. The intended release version for this migration is 8.16. ### Functional tests This PR creates a copy of functional tests for Monaco Console and keeps the tests for Ace in a separate folder. When the migration is released, we can remove the code for Ace together with tests. The Monaco tests are not the exact copy of the Ace tests, since some functionality and autocomplete behaviour is slightly different in the migrated Console. For example, the auto-closing of brackets works in Monaco when typing something, but is not kicking in in the tests. Flaky test runner ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .buildkite/ftr_configs.yml | 3 +- config/serverless.yml | 2 + packages/kbn-monaco/src/console/types.ts | 2 +- .../__snapshots__/code_editor.test.tsx.snap | 1 + .../code_editor/impl/code_editor.tsx | 6 +- .../editor/monaco/monaco_editor.tsx | 2 + .../editor/monaco/monaco_editor_output.tsx | 1 + .../editor/monaco/utils/requests_utils.ts | 4 +- .../editor/monaco/utils/tokens_utils.ts | 2 +- src/plugins/console/server/config.ts | 2 +- .../apps/console/{ => ace}/_autocomplete.ts | 2 +- .../apps/console/{ => ace}/_comments.ts | 2 +- .../apps/console/{ => ace}/_console.ts | 31 +- .../apps/console/{ => ace}/_console_ccs.ts | 2 +- .../apps/console/{ => ace}/_context_menu.ts | 2 +- .../{ => ace}/_misc_console_behavior.ts | 2 +- .../apps/console/{ => ace}/_settings.ts | 2 +- .../apps/console/{ => ace}/_text_input.ts | 2 +- .../apps/console/{ => ace}/_variables.ts | 2 +- .../apps/console/{ => ace}/_vector_tile.ts | 2 +- .../apps/console/{ => ace}/_xjson.ts | 2 +- test/functional/apps/console/ace/config.ts | 27 ++ .../apps/console/{index.js => ace/index.ts} | 4 +- .../apps/console/monaco/_autocomplete.ts | 374 ++++++++++++++++++ .../apps/console/monaco/_comments.ts | 149 +++++++ .../apps/console/monaco/_console.ts | 150 +++++++ .../apps/console/monaco/_console_ccs.ts | 54 +++ .../apps/console/monaco/_context_menu.ts | 104 +++++ .../console/monaco/_misc_console_behavior.ts | 129 ++++++ .../apps/console/monaco/_settings.ts | 41 ++ .../apps/console/monaco/_text_input.ts | 101 +++++ .../apps/console/monaco/_variables.ts | 71 ++++ .../apps/console/monaco/_vector_tile.ts | 51 +++ test/functional/apps/console/monaco/_xjson.ts | 118 ++++++ .../apps/console/{ => monaco}/config.ts | 4 +- test/functional/apps/console/monaco/index.ts | 34 ++ .../controls/common/config.ts | 8 + .../controls/options_list/config.ts | 8 + test/functional/config.ccs.ts | 2 +- test/functional/firefox/console.config.ts | 2 +- test/functional/page_objects/console_page.ts | 160 ++++++++ test/tsconfig.json | 1 + .../apps/reporting_management/config.ts | 8 + 43 files changed, 1626 insertions(+), 50 deletions(-) rename test/functional/apps/console/{ => ace}/_autocomplete.ts (99%) rename test/functional/apps/console/{ => ace}/_comments.ts (98%) rename test/functional/apps/console/{ => ace}/_console.ts (90%) rename test/functional/apps/console/{ => ace}/_console_ccs.ts (96%) rename test/functional/apps/console/{ => ace}/_context_menu.ts (98%) rename test/functional/apps/console/{ => ace}/_misc_console_behavior.ts (98%) rename test/functional/apps/console/{ => ace}/_settings.ts (95%) rename test/functional/apps/console/{ => ace}/_text_input.ts (98%) rename test/functional/apps/console/{ => ace}/_variables.ts (97%) rename test/functional/apps/console/{ => ace}/_vector_tile.ts (96%) rename test/functional/apps/console/{ => ace}/_xjson.ts (99%) create mode 100644 test/functional/apps/console/ace/config.ts rename test/functional/apps/console/{index.js => ace/index.ts} (89%) create mode 100644 test/functional/apps/console/monaco/_autocomplete.ts create mode 100644 test/functional/apps/console/monaco/_comments.ts create mode 100644 test/functional/apps/console/monaco/_console.ts create mode 100644 test/functional/apps/console/monaco/_console_ccs.ts create mode 100644 test/functional/apps/console/monaco/_context_menu.ts create mode 100644 test/functional/apps/console/monaco/_misc_console_behavior.ts create mode 100644 test/functional/apps/console/monaco/_settings.ts create mode 100644 test/functional/apps/console/monaco/_text_input.ts create mode 100644 test/functional/apps/console/monaco/_variables.ts create mode 100644 test/functional/apps/console/monaco/_vector_tile.ts create mode 100644 test/functional/apps/console/monaco/_xjson.ts rename test/functional/apps/console/{ => monaco}/config.ts (87%) create mode 100644 test/functional/apps/console/monaco/index.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index c12bcf333dc08..55f23715e3468 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -98,7 +98,8 @@ enabled: - test/api_integration/config.js - test/examples/config.js - test/functional/apps/bundles/config.ts - - test/functional/apps/console/config.ts + - test/functional/apps/console/monaco/config.ts + - test/functional/apps/console/ace/config.ts - test/functional/apps/context/config.ts - test/functional/apps/dashboard_elements/controls/common/config.ts - test/functional/apps/dashboard_elements/controls/options_list/config.ts diff --git a/config/serverless.yml b/config/serverless.yml index 6658eba7095c1..bea8e422e2925 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -108,6 +108,8 @@ xpack.index_management.enableDataStreamsStorageColumn: false xpack.index_management.enableMappingsSourceFieldSection: false # Disable toggle for enabling data retention in DSL form from Index Management UI xpack.index_management.enableTogglingDataRetention: false +# Disable the Monaco migration in Console +console.dev.enableMonaco: false # Keep deeplinks visible so that they are shown in the sidenav dev_tools.deeplinks.navLinkStatus: visible diff --git a/packages/kbn-monaco/src/console/types.ts b/packages/kbn-monaco/src/console/types.ts index 986ffd6704508..346bd0e6beeeb 100644 --- a/packages/kbn-monaco/src/console/types.ts +++ b/packages/kbn-monaco/src/console/types.ts @@ -15,7 +15,7 @@ export interface ParsedRequest { startOffset: number; endOffset?: number; method: string; - url: string; + url?: string; data?: Array>; } export interface ConsoleParserResult { diff --git a/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap index a538b4845231a..e0fe7d3ea2386 100644 --- a/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap +++ b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap @@ -169,6 +169,7 @@ exports[` is rendered 1`] = `

} + data-test-subj="codeEditorAccessibilityOverlay" delay="regular" display="block" position="top" diff --git a/packages/shared-ux/code_editor/impl/code_editor.tsx b/packages/shared-ux/code_editor/impl/code_editor.tsx index 2e8d2c2732ff7..35dcb275b52f9 100644 --- a/packages/shared-ux/code_editor/impl/code_editor.tsx +++ b/packages/shared-ux/code_editor/impl/code_editor.tsx @@ -155,6 +155,8 @@ export interface CodeEditorProps { * Enables the editor to get disabled when pressing ESC to resolve focus trapping for accessibility. */ accessibilityOverlayEnabled?: boolean; + + dataTestSubj?: string; } export const CodeEditor: React.FC = ({ @@ -186,6 +188,7 @@ export const CodeEditor: React.FC = ({ }), fitToContent, accessibilityOverlayEnabled = true, + dataTestSubj, }) => { const { colorMode, euiTheme } = useEuiTheme(); const useDarkTheme = useDarkThemeProp ?? colorMode === 'DARK'; @@ -280,6 +283,7 @@ export const CodeEditor: React.FC = ({ return ( @@ -485,7 +489,7 @@ export const CodeEditor: React.FC = ({
{accessibilityOverlayEnabled && renderPrompt()} diff --git a/src/plugins/console/public/application/containers/editor/monaco/monaco_editor.tsx b/src/plugins/console/public/application/containers/editor/monaco/monaco_editor.tsx index bc9d6cf2ee3c9..02f978f7919a5 100644 --- a/src/plugins/console/public/application/containers/editor/monaco/monaco_editor.tsx +++ b/src/plugins/console/public/application/containers/editor/monaco/monaco_editor.tsx @@ -115,6 +115,7 @@ export const MonacoEditor = ({ initialTextValue }: EditorProps) => { width: 100%; `} ref={divRef} + data-test-subj="consoleMonacoEditorContainer" > { { { - const url = removeTrailingWhitespaces(parsedRequest.url); - const method = parsedRequest.method.toUpperCase(); + const url = parsedRequest.url ? removeTrailingWhitespaces(parsedRequest.url) : ''; + const method = parsedRequest.method?.toUpperCase() ?? ''; const data = parsedRequest.data?.map((parsedData) => JSON.stringify(parsedData, null, 2)); return { url, method, data: data ?? [] }; }; diff --git a/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts b/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts index f52a0bb6a9079..decbe0d4fdd9a 100644 --- a/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts +++ b/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts @@ -25,7 +25,7 @@ export const parseLine = (line: string): ParsedLineTokens => { // try to parse into method and url (split on whitespace) const parts = line.split(whitespacesRegex); // 1st part is the method - const method = parts[0]; + const method = parts[0].toUpperCase(); // 2nd part is the url const url = parts[1]; // try to parse into url path and url params (split on question mark) diff --git a/src/plugins/console/server/config.ts b/src/plugins/console/server/config.ts index e5a54042f5003..953cc1f84ea60 100644 --- a/src/plugins/console/server/config.ts +++ b/src/plugins/console/server/config.ts @@ -31,7 +31,7 @@ const schemaLatest = schema.object( defaultValue: 'stack', }), }), - dev: schema.object({ enableMonaco: schema.boolean({ defaultValue: false }) }), + dev: schema.object({ enableMonaco: schema.boolean({ defaultValue: true }) }), }, { defaultValue: undefined } ); diff --git a/test/functional/apps/console/_autocomplete.ts b/test/functional/apps/console/ace/_autocomplete.ts similarity index 99% rename from test/functional/apps/console/_autocomplete.ts rename to test/functional/apps/console/ace/_autocomplete.ts index 2f9d8db9cf9d2..fe329e8d2c320 100644 --- a/test/functional/apps/console/_autocomplete.ts +++ b/test/functional/apps/console/ace/_autocomplete.ts @@ -9,7 +9,7 @@ import _ from 'lodash'; import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/console/_comments.ts b/test/functional/apps/console/ace/_comments.ts similarity index 98% rename from test/functional/apps/console/_comments.ts rename to test/functional/apps/console/ace/_comments.ts index de8bcda60786b..8ef708d68b44f 100644 --- a/test/functional/apps/console/_comments.ts +++ b/test/functional/apps/console/ace/_comments.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/ace/_console.ts similarity index 90% rename from test/functional/apps/console/_console.ts rename to test/functional/apps/console/ace/_console.ts index cc3b8dbc7073d..19de1d941fdae 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/ace/_console.ts @@ -8,33 +8,8 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -const DEFAULT_REQUEST = ` -# Welcome to the Dev Tools Console! -# -# You can use Console to explore the Elasticsearch API. See the \n Elasticsearch API reference to learn more: -# https://www.elastic.co/guide/en/elasticsearch/reference/current\n /rest-apis.html -# -# Here are a few examples to get you started. - - -# Create an index -PUT /my-index - - -# Add a document to my-index -POST /my-index/_doc -{ - "id": "park_rocky-mountain", - "title": "Rocky Mountain", - "description": "Bisected north to south by the Continental \n Divide, this portion of the Rockies has ecosystems varying \n from over 150 riparian lakes to montane and subalpine forests \n to treeless alpine tundra." -} - - -# Perform a search in my-index -GET /my-index/_search?q="rocky mountain" -`.trim(); +import { DEFAULT_INPUT_VALUE } from '@kbn/console-plugin/common/constants'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); @@ -58,7 +33,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const actualRequest = await PageObjects.console.getRequest(); log.debug(actualRequest); - expect(actualRequest.trim()).to.eql(DEFAULT_REQUEST); + expect(actualRequest.replace(/\s/g, '')).to.eql(DEFAULT_INPUT_VALUE.replace(/\s/g, '')); }); }); diff --git a/test/functional/apps/console/_console_ccs.ts b/test/functional/apps/console/ace/_console_ccs.ts similarity index 96% rename from test/functional/apps/console/_console_ccs.ts rename to test/functional/apps/console/ace/_console_ccs.ts index 8778c2e6e70bb..57ab547af4e49 100644 --- a/test/functional/apps/console/_console_ccs.ts +++ b/test/functional/apps/console/ace/_console_ccs.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/console/_context_menu.ts b/test/functional/apps/console/ace/_context_menu.ts similarity index 98% rename from test/functional/apps/console/_context_menu.ts rename to test/functional/apps/console/ace/_context_menu.ts index 4051804d7407f..677aa1c43fe39 100644 --- a/test/functional/apps/console/_context_menu.ts +++ b/test/functional/apps/console/ace/_context_menu.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/console/_misc_console_behavior.ts b/test/functional/apps/console/ace/_misc_console_behavior.ts similarity index 98% rename from test/functional/apps/console/_misc_console_behavior.ts rename to test/functional/apps/console/ace/_misc_console_behavior.ts index 2920813f2cca0..303004ad42446 100644 --- a/test/functional/apps/console/_misc_console_behavior.ts +++ b/test/functional/apps/console/ace/_misc_console_behavior.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/console/_settings.ts b/test/functional/apps/console/ace/_settings.ts similarity index 95% rename from test/functional/apps/console/_settings.ts rename to test/functional/apps/console/ace/_settings.ts index a2802db67e859..f42a078ff48e7 100644 --- a/test/functional/apps/console/_settings.ts +++ b/test/functional/apps/console/ace/_settings.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/console/_text_input.ts b/test/functional/apps/console/ace/_text_input.ts similarity index 98% rename from test/functional/apps/console/_text_input.ts rename to test/functional/apps/console/ace/_text_input.ts index 8826b24931c07..b60a3b8df8f79 100644 --- a/test/functional/apps/console/_text_input.ts +++ b/test/functional/apps/console/ace/_text_input.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/console/_variables.ts b/test/functional/apps/console/ace/_variables.ts similarity index 97% rename from test/functional/apps/console/_variables.ts rename to test/functional/apps/console/ace/_variables.ts index 8e09460b4dc6c..91474de06d678 100644 --- a/test/functional/apps/console/_variables.ts +++ b/test/functional/apps/console/ace/_variables.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ getService, getPageObjects }: FtrProviderContext) => { const retry = getService('retry'); diff --git a/test/functional/apps/console/_vector_tile.ts b/test/functional/apps/console/ace/_vector_tile.ts similarity index 96% rename from test/functional/apps/console/_vector_tile.ts rename to test/functional/apps/console/ace/_vector_tile.ts index 77b186227ed28..376bf5ccb7eef 100644 --- a/test/functional/apps/console/_vector_tile.ts +++ b/test/functional/apps/console/ace/_vector_tile.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'console', 'header', 'home']); diff --git a/test/functional/apps/console/_xjson.ts b/test/functional/apps/console/ace/_xjson.ts similarity index 99% rename from test/functional/apps/console/_xjson.ts rename to test/functional/apps/console/ace/_xjson.ts index 6a4f352a3ad01..ae9bfb519ba67 100644 --- a/test/functional/apps/console/_xjson.ts +++ b/test/functional/apps/console/ace/_xjson.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { rgbToHex } from '@elastic/eui'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ getService, getPageObjects }: FtrProviderContext) => { const retry = getService('retry'); diff --git a/test/functional/apps/console/ace/config.ts b/test/functional/apps/console/ace/config.ts new file mode 100644 index 0000000000000..013c5b26d0cdb --- /dev/null +++ b/test/functional/apps/console/ace/config.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; +import { configureHTTP2 } from '../../../../common/configure_http2'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return configureHTTP2({ + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + // disabling the monaco editor to run tests for ace + `--console.dev.enableMonaco=false`, + ], + }, + }); +} diff --git a/test/functional/apps/console/index.js b/test/functional/apps/console/ace/index.ts similarity index 89% rename from test/functional/apps/console/index.js rename to test/functional/apps/console/ace/index.ts index 36fb3f5421540..7274118daaafe 100644 --- a/test/functional/apps/console/index.js +++ b/test/functional/apps/console/ace/index.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ -export default function ({ getService, loadTestFile }) { +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { const browser = getService('browser'); const config = getService('config'); diff --git a/test/functional/apps/console/monaco/_autocomplete.ts b/test/functional/apps/console/monaco/_autocomplete.ts new file mode 100644 index 0000000000000..e6ed83ad26338 --- /dev/null +++ b/test/functional/apps/console/monaco/_autocomplete.ts @@ -0,0 +1,374 @@ +/* + * Copyright 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 _ from 'lodash'; +import expect from '@kbn/expect'; +import { asyncForEach } from '@kbn/std'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const log = getService('log'); + const retry = getService('retry'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + const find = getService('find'); + + describe('console autocomplete feature', function describeIndexTests() { + this.tags('includeFirefox'); + before(async () => { + log.debug('navigateTo console'); + await PageObjects.common.navigateToApp('console'); + // Ensure that the text area can be interacted with + await PageObjects.console.closeHelpIfExists(); + await PageObjects.console.monaco.clearEditorText(); + log.debug('setAutocompleteTrace true'); + await PageObjects.console.setAutocompleteTrace(true); + }); + + after(async () => { + log.debug('setAutocompleteTrace false'); + await PageObjects.console.setAutocompleteTrace(false); + }); + + it('should provide basic auto-complete functionality', async () => { + await PageObjects.console.monaco.enterText(`GET _search\n`); + await PageObjects.console.monaco.pressEnter(); + await PageObjects.console.monaco.enterText(`{\n\t"query": {`); + await PageObjects.console.monaco.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); + await PageObjects.console.monaco.promptAutocomplete(); + expect(PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + }); + + describe('Autocomplete behavior', () => { + beforeEach(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + + it('HTTP methods', async () => { + const suggestions = { + G: ['GET'], + P: ['PATCH', 'POST', 'PUT'], + D: ['DELETE'], + H: ['HEAD'], + }; + for (const [char, methods] of Object.entries(suggestions)) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char); + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + + for (const [i, method] of methods.entries()) { + expect(await PageObjects.console.monaco.getAutocompleteSuggestion(i)).to.be.eql(method); + } + + await PageObjects.console.monaco.pressEscape(); + await PageObjects.console.monaco.clearEditorText(); + } + }); + + it('ES API endpoints', async () => { + const suggestions = { + 'GET _': ['_alias', '_all'], + 'PUT _': ['_all'], + 'POST _': ['_aliases', '_all'], + 'DELETE _': ['_all'], + 'HEAD _': ['_alias', '_all'], + }; + for (const [text, endpoints] of Object.entries(suggestions)) { + for (const char of text) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char); + } + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + + for (const [i, endpoint] of endpoints.entries()) { + expect(await PageObjects.console.monaco.getAutocompleteSuggestion(i)).to.be.eql( + endpoint + ); + } + + await PageObjects.console.monaco.pressEscape(); + await PageObjects.console.monaco.pressEnter(); + } + }); + + it('JSON autocompletion with placeholder fields', async () => { + await PageObjects.console.monaco.enterText('GET _search\n'); + await PageObjects.console.monaco.enterText('{'); + await PageObjects.console.monaco.pressEnter(); + + for (const char of '"ag') { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char); + } + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + await PageObjects.console.monaco.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); + + expect((await PageObjects.console.monaco.getEditorText()).replace(/\s/g, '')).to.be.eql( + ` +GET _search +{ + "aggs": { + "NAME": { + "AGG_TYPE": {} + } + } +} +`.replace(/\s/g, '') + ); + }); + + it('Dynamic autocomplete', async () => { + await PageObjects.console.monaco.enterText('POST test/_doc\n{}'); + await PageObjects.console.clickPlay(); + + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await PageObjects.console.getResponseStatus()).to.be('201'); + + await PageObjects.console.monaco.pressEnter(); + for (const char of 'POST t') { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char); + } + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + + expect(await PageObjects.console.monaco.getAutocompleteSuggestion(0)).to.be.eql('test'); + }); + }); + + describe('anti-regression watchdogs', () => { + beforeEach(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + + // flaky + it.skip('should suppress auto-complete on arrow keys', async () => { + await PageObjects.console.monaco.enterText(`\nGET _search\nGET _search`); + await PageObjects.console.monaco.pressEnter(); + const keyPresses = [ + 'pressUp', + 'pressUp', + 'pressDown', + 'pressDown', + 'pressRight', + 'pressRight', + 'pressLeft', + 'pressLeft', + ] as const; + for (const keyPress of keyPresses) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key', keyPress); + await PageObjects.console.monaco[keyPress](); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(false); + } + }); + + it('should activate auto-complete for methods case-insensitively', async () => { + const methods = _.sampleSize( + _.compact( + ` + GET GEt GeT Get gET gEt geT get + PUT PUt PuT Put pUT pUt puT put + POST POSt POsT POst PoST PoSt PosT Post pOST pOSt pOsT pOst poST poSt posT post + DELETE DELETe DELEtE DELEte DELeTE DELeTe DELetE DELete DElETE DElETe DElEtE DElEte DEleTE DEleTe DEletE DElete + DeLETE DeLETe DeLEtE DeLEte DeLeTE DeLeTe DeLetE DeLete DelETE DelETe DelEtE DelEte DeleTE DeleTe DeletE Delete + dELETE dELETe dELEtE dELEte dELeTE dELeTe dELetE dELete dElETE dElETe dElEtE dElEte dEleTE dEleTe dEletE dElete + deLETE deLETe deLEtE deLEte deLeTE deLeTe deLetE deLete delETE delETe delEtE delEte deleTE deleTe deletE delete + HEAD HEAd HEaD HEad HeAD HeAd HeaD Head hEAD hEAd hEaD hEad heAD heAd heaD head + `.split(/\s+/m) + ), + 20 // 20 of 112 (approx. one-fifth) should be enough for testing + ); + + for (const method of methods) { + await PageObjects.console.monaco.clearEditorText(); + + for (const char of method.slice(0, -1)) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char); // e.g. 'P' -> 'Po' -> 'Pos' + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + } + + for (const char of [method.at(-1), ' ', '_']) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char!); // e.g. 'Post ' -> 'Post _' + } + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + } + }); + + it('should activate auto-complete for a single character immediately following a slash in URL', async () => { + await PageObjects.console.monaco.enterText('GET .kibana'); + + for (const char of ['/', '_']) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.monaco.enterText(char); // i.e. 'GET .kibana/' -> 'GET .kibana/_' + } + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + }); + + it('should activate auto-complete for multiple indices after comma in URL', async () => { + await PageObjects.console.monaco.enterText('GET _cat/indices/.kibana'); + + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type ","'); + await PageObjects.console.monaco.enterText(','); // i.e. 'GET /_cat/indices/.kibana,' + + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type Ctrl+SPACE'); + await PageObjects.console.monaco.pressCtrlSpace(); + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(true); + }); + + // not fixed for monaco yet https://github.com/elastic/kibana/issues/184442 + it.skip('should not activate auto-complete after comma following endpoint in URL', async () => { + await PageObjects.console.monaco.enterText('GET _search'); + + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type ","'); + await PageObjects.console.monaco.enterText(','); // i.e. 'GET _search,' + + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type Ctrl+SPACE'); + await PageObjects.console.monaco.pressCtrlSpace(); + + expect(await PageObjects.console.monaco.isAutocompleteVisible()).to.be.eql(false); + }); + }); + + // not implemented for monaco yet https://github.com/elastic/kibana/issues/184856 + describe.skip('with a missing comma in query', () => { + const LINE_NUMBER = 4; + beforeEach(async () => { + await PageObjects.console.clearTextArea(); + await PageObjects.console.enterRequest(); + await PageObjects.console.pressEnter(); + }); + + it('should add a comma after previous non empty line', async () => { + await PageObjects.console.enterText(`{\n\t"query": {\n\t\t"match": {}`); + await PageObjects.console.pressEnter(); + await PageObjects.console.pressEnter(); + await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); + await PageObjects.console.promptAutocomplete(); + await PageObjects.console.pressEnter(); + await retry.try(async () => { + let conApp = await find.byCssSelector('.conApp'); + const firstInnerHtml = await conApp.getAttribute('innerHTML'); + await PageObjects.common.sleep(500); + conApp = await find.byCssSelector('.conApp'); + const secondInnerHtml = await conApp.getAttribute('innerHTML'); + return firstInnerHtml === secondInnerHtml; + }); + const textAreaString = await PageObjects.console.getAllVisibleText(); + log.debug('Text Area String Value==================\n'); + log.debug(textAreaString); + expect(textAreaString).to.contain(','); + const text = await PageObjects.console.getVisibleTextAt(LINE_NUMBER); + const lastChar = text.charAt(text.length - 1); + expect(lastChar).to.be.eql(','); + }); + + it('should add a comma after the triple quoted strings', async () => { + await PageObjects.console.enterText(`{\n\t"query": {\n\t\t"term": """some data"""`); + await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); + await PageObjects.console.promptAutocomplete(); + await PageObjects.console.pressEnter(); + + await retry.waitForWithTimeout('text area to contain comma', 25000, async () => { + const textAreaString = await PageObjects.console.getAllVisibleText(); + return textAreaString.includes(','); + }); + + const text = await PageObjects.console.getVisibleTextAt(LINE_NUMBER); + const lastChar = text.charAt(text.length - 1); + expect(lastChar).to.be.eql(','); + }); + }); + + describe('with conditional templates', async () => { + const CONDITIONAL_TEMPLATES = [ + { + type: 'fs', + template: `"location": "path"`, + }, + { + type: 'url', + template: `"url": ""`, + }, + { type: 's3', template: `"bucket": ""` }, + { + type: 'azure', + template: `"path": ""`, + }, + ]; + + beforeEach(async () => { + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.enterText('POST _snapshot/test_repo\n'); + }); + + await asyncForEach(CONDITIONAL_TEMPLATES, async ({ type, template }) => { + it('should insert different templates depending on the value of type', async () => { + await PageObjects.console.monaco.enterText(`{\n\t"type": "${type}",\n`); + await PageObjects.console.sleepForDebouncePeriod(); + // Prompt autocomplete for 'settings' + await PageObjects.console.monaco.promptAutocomplete('s'); + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.monaco.isAutocompleteVisible() + ); + await PageObjects.console.monaco.pressEnter(); + await retry.try(async () => { + const request = await PageObjects.console.monaco.getEditorText(); + log.debug(request); + expect(request).to.contain(`${template}`); + }); + }); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_comments.ts b/test/functional/apps/console/monaco/_comments.ts new file mode 100644 index 0000000000000..ba8d8b6f04f07 --- /dev/null +++ b/test/functional/apps/console/monaco/_comments.ts @@ -0,0 +1,149 @@ +/* + * Copyright 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 expect from '@kbn/expect'; +import { asyncForEach } from '@kbn/std'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const log = getService('log'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + + // flaky + describe.skip('console app', function testComments() { + this.tags('includeFirefox'); + before(async () => { + log.debug('navigateTo console'); + await PageObjects.common.navigateToApp('console'); + await PageObjects.console.closeHelpIfExists(); + }); + + describe('with comments', async () => { + const enterRequest = async (url: string, body: string) => { + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.enterText(`${url}\n${body}`); + }; + + async function runTests( + tests: Array<{ description: string; url?: string; body: string }>, + fn: () => Promise + ) { + await asyncForEach(tests, async ({ description, url, body }) => { + it(description, async () => { + await enterRequest(url ?? '\nGET search', body); + await fn(); + }); + }); + } + + describe('with single line comments', async () => { + await runTests( + [ + { + url: '\n// GET _search', + body: '', + description: 'should allow in request url, using //', + }, + { + body: '{\n\t\t"query": {\n\t\t\t// "match_all": {}\n}\n}', + description: 'should allow in request body, using //', + }, + { + url: '\n # GET _search', + body: '', + description: 'should allow in request url, using #', + }, + { + body: '{\n\t\t"query": {\n\t\t\t# "match_all": {}\n}\n}', + description: 'should allow in request body, using #', + }, + { + description: 'should accept as field names, using //', + body: '{\n "//": {} }', + }, + { + description: 'should accept as field values, using //', + body: '{\n "f": "//" }', + }, + { + description: 'should accept as field names, using #', + body: '{\n "#": {} }', + }, + { + description: 'should accept as field values, using #', + body: '{\n "f": "#" }', + }, + ], + async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + } + ); + }); + + describe('with multiline comments', async () => { + await runTests( + [ + { + url: '\n /* \nGET _search \n*/', + body: '', + description: 'should allow in request url, using /* */', + }, + { + body: '{\n\t\t"query": {\n\t\t\t/* "match_all": {} */ \n}\n}', + description: 'should allow in request body, using /* */', + }, + { + description: 'should accept as field names, using /*', + body: '{\n "/*": {} \n\t\t /* "f": 1 */ \n}', + }, + { + description: 'should accept as field values, using */', + body: '{\n /* "f": 1 */ \n"f": "*/" \n}', + }, + ], + async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + } + ); + }); + + describe('with invalid syntax in request body', async () => { + await runTests( + [ + { + description: 'should highlight invalid syntax', + body: '{\n "query": \'\'', // E.g. using single quotes + }, + ], + + async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(true); + } + ); + }); + + describe('with invalid request', async () => { + await runTests( + [ + { + description: 'with invalid character should display error marker', + body: '{\n $ "query": {}', + }, + { + description: 'with missing field name', + body: '{\n "query": {},\n {}', + }, + ], + async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(true); + } + ); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_console.ts b/test/functional/apps/console/monaco/_console.ts new file mode 100644 index 0000000000000..36bb893d5b90f --- /dev/null +++ b/test/functional/apps/console/monaco/_console.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 expect from '@kbn/expect'; +import { asyncForEach } from '@kbn/std'; +import { DEFAULT_INPUT_VALUE } from '@kbn/console-plugin/common/constants'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const log = getService('log'); + const browser = getService('browser'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + const security = getService('security'); + + describe('console app', function describeIndexTests() { + this.tags('includeFirefox'); + before(async () => { + log.debug('navigateTo console'); + await PageObjects.common.navigateToApp('console'); + }); + beforeEach(async () => { + await PageObjects.console.closeHelpIfExists(); + }); + + it('should show the default request', async () => { + await retry.try(async () => { + const actualRequest = await PageObjects.console.monaco.getEditorText(); + log.debug(actualRequest); + expect(actualRequest.replace(/\s/g, '')).to.eql(DEFAULT_INPUT_VALUE.replace(/\s/g, '')); + }); + }); + + // issue with the url params with whitespaces https://github.com/elastic/kibana/issues/184927 + it.skip('default request response should include `"timed_out" : false`', async () => { + const expectedResponseContains = `"timed_out": false`; + await PageObjects.console.monaco.selectAllRequests(); + await PageObjects.console.clickPlay(); + await retry.try(async () => { + const actualResponse = await PageObjects.console.monaco.getOutputText(); + log.debug(actualResponse); + expect(actualResponse).to.contain(expectedResponseContains); + }); + }); + + // the resizer doesn't work the same as in ace https://github.com/elastic/kibana/issues/184352 + it.skip('should resize the editor', async () => { + const editor = await PageObjects.console.monaco.getEditor(); + await browser.setWindowSize(1300, 1100); + const initialSize = await editor.getSize(); + await browser.setWindowSize(1000, 1100); + const afterSize = await editor.getSize(); + expect(initialSize.width).to.be.greaterThan(afterSize.width); + }); + + it('should return statusCode 400 to unsupported HTTP verbs', async () => { + const expectedResponseContains = '"statusCode": 400'; + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.enterText('OPTIONS /'); + await PageObjects.console.clickPlay(); + await retry.try(async () => { + const actualResponse = await PageObjects.console.monaco.getOutputText(); + log.debug(actualResponse); + expect(actualResponse).to.contain(expectedResponseContains); + + expect(await PageObjects.console.hasSuccessBadge()).to.be(false); + }); + }); + + describe('with kbn: prefix in request', () => { + before(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + it('it should send successful request to Kibana API', async () => { + const expectedResponseContains = 'default space'; + await PageObjects.console.monaco.enterText('GET kbn:/api/spaces/space'); + await PageObjects.console.clickPlay(); + await retry.try(async () => { + const actualResponse = await PageObjects.console.monaco.getOutputText(); + log.debug(actualResponse); + expect(actualResponse).to.contain(expectedResponseContains); + }); + }); + }); + + describe('with query params', () => { + it('should issue a successful request', async () => { + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.enterText( + 'GET _cat/aliases?format=json&v=true&pretty=true' + ); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + // set the width of the browser, so that the response status is visible + await browser.setWindowSize(1300, 1100); + await retry.try(async () => { + const status = await PageObjects.console.getResponseStatus(); + expect(status).to.eql(200); + }); + }); + }); + + describe('multiple requests output', function () { + const sendMultipleRequests = async (requests: string[]) => { + await asyncForEach(requests, async (request) => { + await PageObjects.console.monaco.enterText(request); + }); + await PageObjects.console.monaco.selectAllRequests(); + await PageObjects.console.clickPlay(); + }; + + before(async () => { + await security.testUser.setRoles(['kibana_admin', 'test_index']); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + }); + + beforeEach(async () => { + await PageObjects.console.closeHelpIfExists(); + await PageObjects.console.monaco.clearEditorText(); + }); + + it('should contain comments starting with # symbol', async () => { + await sendMultipleRequests(['\n PUT test-index', '\n DELETE test-index']); + await retry.try(async () => { + const response = await PageObjects.console.monaco.getOutputText(); + log.debug(response); + expect(response).to.contain('# PUT test-index 200'); + expect(response).to.contain('# DELETE test-index 200'); + }); + }); + + // not implemented for monaco yet https://github.com/elastic/kibana/issues/184010 + it.skip('should display status badges', async () => { + await sendMultipleRequests(['\n GET _search/test', '\n GET _search']); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await PageObjects.console.hasWarningBadge()).to.be(true); + expect(await PageObjects.console.hasSuccessBadge()).to.be(true); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_console_ccs.ts b/test/functional/apps/console/monaco/_console_ccs.ts new file mode 100644 index 0000000000000..410518a6bfc81 --- /dev/null +++ b/test/functional/apps/console/monaco/_console_ccs.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const log = getService('log'); + const browser = getService('browser'); + const PageObjects = getPageObjects(['common', 'console']); + const remoteEsArchiver = getService('remoteEsArchiver' as 'esArchiver'); + + describe('Console App CCS', function describeIndexTests() { + this.tags('includeFirefox'); + before(async () => { + await remoteEsArchiver.loadIfNeeded( + 'test/functional/fixtures/es_archiver/logstash_functional' + ); + // resize the editor to allow the whole of the response to be displayed + await browser.setWindowSize(1200, 1800); + log.debug('navigateTo console'); + await PageObjects.common.navigateToApp('console'); + await retry.try(async () => { + await PageObjects.console.collapseHelp(); + }); + }); + + after(async () => { + await remoteEsArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + describe('Perform CCS Search in Console', () => { + before(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + it('it should be able to access remote data', async () => { + await PageObjects.console.monaco.enterText( + '\nGET ftr-remote:logstash-*/_search\n {\n "query": {\n "bool": {\n "must": [\n {"match": {"extension" : "jpg"} \n}\n]\n}\n}\n}' + ); + await PageObjects.console.clickPlay(); + await retry.try(async () => { + const actualResponse = await PageObjects.console.monaco.getOutputText(); + expect(actualResponse).to.contain('"_index": "ftr-remote:logstash-2015.09.20"'); + }); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_context_menu.ts b/test/functional/apps/console/monaco/_context_menu.ts new file mode 100644 index 0000000000000..f74e9d2814242 --- /dev/null +++ b/test/functional/apps/console/monaco/_context_menu.ts @@ -0,0 +1,104 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const log = getService('log'); + const retry = getService('retry'); + const PageObjects = getPageObjects(['common', 'console']); + const browser = getService('browser'); + const toasts = getService('toasts'); + + describe('console context menu', function testContextMenu() { + before(async () => { + await PageObjects.common.navigateToApp('console'); + // Ensure that the text area can be interacted with + await PageObjects.console.closeHelpIfExists(); + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.enterText('GET _search'); + }); + + it('should open context menu', async () => { + expect(await PageObjects.console.isContextMenuOpen()).to.be(false); + await PageObjects.console.clickContextMenu(); + expect(PageObjects.console.isContextMenuOpen()).to.be.eql(true); + }); + + it('should have options to copy as curl, open documentation, and auto indent', async () => { + await PageObjects.console.clickContextMenu(); + expect(PageObjects.console.isContextMenuOpen()).to.be.eql(true); + expect(PageObjects.console.isCopyAsCurlButtonVisible()).to.be.eql(true); + expect(PageObjects.console.isOpenDocumentationButtonVisible()).to.be.eql(true); + expect(PageObjects.console.isAutoIndentButtonVisible()).to.be.eql(true); + }); + + it('should copy as curl and show toast when copy as curl button is clicked', async () => { + await PageObjects.console.clickContextMenu(); + await PageObjects.console.clickCopyAsCurlButton(); + + const resultToast = await toasts.getElementByIndex(1); + const toastText = await resultToast.getVisibleText(); + + if (toastText.includes('Write permission denied')) { + log.debug('Write permission denied, skipping test'); + return; + } + + expect(toastText).to.be('Request copied as cURL'); + + const canReadClipboard = await browser.checkBrowserPermission('clipboard-read'); + if (canReadClipboard) { + const clipboardText = await browser.getClipboardValue(); + expect(clipboardText).to.contain('curl -XGET'); + } + }); + + it('should open documentation when open documentation button is clicked', async () => { + await PageObjects.console.clickContextMenu(); + await PageObjects.console.clickOpenDocumentationButton(); + + await retry.tryForTime(10000, async () => { + await browser.switchTab(1); + }); + + // Retry until the documentation is loaded + await retry.try(async () => { + const url = await browser.getCurrentUrl(); + expect(url).to.contain('search-search.html'); + }); + + // Close the documentation tab + await browser.closeCurrentWindow(); + await browser.switchTab(0); + }); + + // not implemented yet for monaco https://github.com/elastic/kibana/issues/185891 + it.skip('should toggle auto indent when auto indent button is clicked', async () => { + await PageObjects.console.clearTextArea(); + await PageObjects.console.enterRequest('GET _search\n{"query": {"match_all": {}}}'); + await PageObjects.console.clickContextMenu(); + await PageObjects.console.clickAutoIndentButton(); + // Retry until the request is auto indented + await retry.try(async () => { + const request = await PageObjects.console.getRequest(); + expect(request).to.be.eql('GET _search\n{\n "query": {\n "match_all": {}\n }\n}'); + }); + + await PageObjects.console.clickContextMenu(); + // Click the auto-indent button again to condense request + await PageObjects.console.clickAutoIndentButton(); + // Retry until the request is condensed + await retry.try(async () => { + const request = await PageObjects.console.getRequest(); + expect(request).to.be.eql('GET _search\n{"query":{"match_all":{}}}'); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_misc_console_behavior.ts b/test/functional/apps/console/monaco/_misc_console_behavior.ts new file mode 100644 index 0000000000000..bc179ccc83208 --- /dev/null +++ b/test/functional/apps/console/monaco/_misc_console_behavior.ts @@ -0,0 +1,129 @@ +/* + * Copyright 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const browser = getService('browser'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + + describe('misc console behavior', function testMiscConsoleBehavior() { + this.tags('includeFirefox'); + before(async () => { + await browser.setWindowSize(1200, 800); + await PageObjects.common.navigateToApp('console'); + // Ensure that the text area can be interacted with + await PageObjects.console.closeHelpIfExists(); + }); + + beforeEach(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + + describe('keyboard shortcuts', () => { + let tabCount = 1; + + after(async () => { + if (tabCount > 1) { + await browser.closeCurrentWindow(); + await browser.switchTab(0); + } + }); + + it('should execute the request when Ctrl+Enter is pressed', async () => { + await PageObjects.console.monaco.enterText('GET _search'); + await PageObjects.console.monaco.pressCtrlEnter(); + await retry.try(async () => { + const response = await PageObjects.console.monaco.getOutputText(); + expect(response).to.contain('"timed_out": false'); + }); + }); + + it('should auto indent current request when Ctrl+I is pressed', async () => { + await PageObjects.console.monaco.enterText('GET _search\n{"query": {"match_all": {}}}'); + await PageObjects.console.monaco.selectCurrentRequest(); + await PageObjects.console.monaco.pressCtrlI(); + await retry.waitFor('request to be auto indented', async () => { + const request = await PageObjects.console.monaco.getEditorText(); + return request === 'GET _search\n{\n "query": {\n "match_all": {}\n }\n}'; + }); + }); + + it('should jump to the previous request when Ctrl+Up is pressed', async () => { + await PageObjects.console.monaco.enterText('\nGET _search/foo'); + await PageObjects.console.monaco.enterText('\nGET _search/bar'); + await PageObjects.console.monaco.pressCtrlUp(); + await retry.waitFor('request to be selected', async () => { + const request = await PageObjects.console.monaco.getEditorTextAtLine(1); + return request === 'GET _search/foo'; + }); + }); + + it('should jump to the next request when Ctrl+Down is pressed', async () => { + await PageObjects.console.monaco.enterText('\nGET _search/foo'); + await PageObjects.console.monaco.enterText('\nGET _search/bar'); + await PageObjects.console.monaco.pressCtrlUp(); + await PageObjects.console.monaco.pressCtrlDown(); + await retry.waitFor('request to be selected', async () => { + const request = await PageObjects.console.monaco.getEditorTextAtLine(2); + return request === 'GET _search/bar'; + }); + }); + + // flaky + it.skip('should go to line number when Ctrl+L is pressed', async () => { + await PageObjects.console.monaco.enterText( + '\nGET _search/foo\n{\n "query": {\n "match_all": {} \n} \n}' + ); + await PageObjects.console.monaco.pressCtrlL(); + // Sleep to allow the line number input to be focused + await PageObjects.common.sleep(1000); + const alert = await browser.getAlert(); + await alert?.sendKeys('4'); + await alert?.accept(); + await PageObjects.common.sleep(1000); + expect(await PageObjects.console.monaco.getCurrentLineNumber()).to.be(4); + }); + + // flaky + it.skip('should open documentation when Ctrl+/ is pressed', async () => { + await PageObjects.console.monaco.enterText('GET _search'); + await PageObjects.console.monaco.pressEscape(); + await PageObjects.console.monaco.pressCtrlSlash(); + await retry.tryForTime(10000, async () => { + await browser.switchTab(1); + tabCount++; + }); + + // Retry until the documentation is loaded + await retry.try(async () => { + const url = await browser.getCurrentUrl(); + expect(url).to.contain('search-search.html'); + }); + }); + }); + + describe('customizable font size', () => { + // flaky + it.skip('should allow the font size to be customized', async () => { + await PageObjects.console.setFontSizeSetting(20); + await retry.try(async () => { + // the settings are not applied synchronously, so we retry for a time + expect(await PageObjects.console.monaco.getFontSize()).to.be('20px'); + }); + + await PageObjects.console.setFontSizeSetting(24); + await retry.try(async () => { + // the settings are not applied synchronously, so we retry for a time + expect(await PageObjects.console.monaco.getFontSize()).to.be('24px'); + }); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_settings.ts b/test/functional/apps/console/monaco/_settings.ts new file mode 100644 index 0000000000000..f998a281b560d --- /dev/null +++ b/test/functional/apps/console/monaco/_settings.ts @@ -0,0 +1,41 @@ +/* + * Copyright 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const log = getService('log'); + const PageObjects = getPageObjects(['common', 'console']); + + describe('console settings', function testSettings() { + this.tags('includeFirefox'); + before(async () => { + log.debug('navigateTo console'); + await PageObjects.common.navigateToApp('console'); + // Ensure that the text area can be interacted with + await PageObjects.console.closeHelpIfExists(); + await PageObjects.console.monaco.clearEditorText(); + }); + + it('displays the a11y overlay', async () => { + await PageObjects.console.monaco.pressEscape(); + const isOverlayVisible = await PageObjects.console.monaco.isA11yOverlayVisible(); + expect(isOverlayVisible).to.be(true); + }); + + it('disables the a11y overlay via settings', async () => { + await PageObjects.console.openSettings(); + await PageObjects.console.toggleA11yOverlaySetting(); + + await PageObjects.console.monaco.pressEscape(); + const isOverlayVisible = await PageObjects.console.monaco.isA11yOverlayVisible(); + expect(isOverlayVisible).to.be(false); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_text_input.ts b/test/functional/apps/console/monaco/_text_input.ts new file mode 100644 index 0000000000000..b238a557bbb38 --- /dev/null +++ b/test/functional/apps/console/monaco/_text_input.ts @@ -0,0 +1,101 @@ +/* + * Copyright 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const toasts = getService('toasts'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + + describe('text input', function testTextInput() { + before(async () => { + await PageObjects.common.navigateToApp('console'); + await PageObjects.console.closeHelpIfExists(); + }); + + beforeEach(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + + describe('with a data URI in the load_from query', () => { + it('loads the data from the URI', async () => { + await PageObjects.common.navigateToApp('console', { + hash: '#/console?load_from=data:text/plain,BYUwNmD2Q', + }); + + await retry.try(async () => { + const actualRequest = await PageObjects.console.monaco.getEditorText(); + expect(actualRequest.trim()).to.eql('hello'); + }); + }); + + describe('with invalid data', () => { + it('shows a toast error', async () => { + await PageObjects.common.navigateToApp('console', { + hash: '#/console?load_from=data:text/plain,BYUwNmD2', + }); + + await retry.try(async () => { + expect(await toasts.getCount()).to.equal(1); + }); + }); + }); + }); + + // not yet implemented for monaco https://github.com/elastic/kibana/issues/186001 + describe.skip('copy/pasting cURL commands into the console', () => { + it('should convert cURL commands into the console request format', async () => { + await PageObjects.console.monaco.enterText( + `\n curl -XGET "http://localhost:9200/_search?pretty" -d'\n{"query": {"match_all": {}}}'` + ); + await PageObjects.console.monaco.copyRequestsToClipboard(); + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.pasteClipboardValue(); + await retry.try(async () => { + const actualRequest = await PageObjects.console.monaco.getEditorText(); + expect(actualRequest.trim()).to.eql('GET /_search?pretty\n {"query": {"match_all": {}}}'); + }); + }); + }); + + describe('console history', () => { + const sendRequest = async (request: string) => { + await PageObjects.console.monaco.enterText(request); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + }; + + it('should show the history', async () => { + await sendRequest('GET /_search?pretty'); + await PageObjects.console.clickHistory(); + await retry.try(async () => { + const history = await PageObjects.console.getHistoryEntries(); + expect(history).to.eql(['/_search?pretty (a few seconds ago)']); + }); + + // Clear the history + await PageObjects.console.clickClearHistory(); + await PageObjects.console.closeHistory(); + }); + + it('should load a request from history', async () => { + await sendRequest('GET _search\n{"query": {"match_all": {}}}'); + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.clickHistory(); + await PageObjects.console.loadRequestFromHistory(0); + await retry.try(async () => { + const actualRequest = await PageObjects.console.monaco.getEditorText(); + expect(actualRequest.trim()).to.eql( + 'GET _search\n{\n "query": {\n "match_all": {}\n }\n}' + ); + }); + }); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_variables.ts b/test/functional/apps/console/monaco/_variables.ts new file mode 100644 index 0000000000000..5d8719e9ea4d3 --- /dev/null +++ b/test/functional/apps/console/monaco/_variables.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getService, getPageObjects }: FtrProviderContext) => { + const retry = getService('retry'); + const log = getService('log'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + + describe('Console variables', function testConsoleVariables() { + // FLAKY on firefox: https://github.com/elastic/kibana/issues/157776 + // this.tags('includeFirefox'); + before(async () => { + log.debug('navigateTo console'); + await PageObjects.common.navigateToApp('console'); + await PageObjects.console.closeHelpIfExists(); + await PageObjects.console.monaco.clearEditorText(); + }); + + it('should allow creating a new variable', async () => { + await PageObjects.console.addNewVariable({ name: 'index1', value: 'test' }); + const variables = await PageObjects.console.getVariables(); + log.debug(variables); + expect(variables).to.contain('index1'); + }); + + it('should allow removing a variable', async () => { + await PageObjects.console.addNewVariable({ name: 'index2', value: 'test' }); + await PageObjects.console.removeVariables(); + const variables = await PageObjects.console.getVariables(); + expect(variables).to.eql([]); + }); + + describe('with variables in url', () => { + it('should send a successful request', async () => { + await PageObjects.console.addNewVariable({ name: 'index3', value: '_search' }); + await PageObjects.console.monaco.enterText('\n GET ${index3}'); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.try(async () => { + const status = await PageObjects.console.getResponseStatus(); + expect(status).to.eql(200); + }); + }); + }); + + describe('with variables in request body', () => { + // bug in monaco https://github.com/elastic/kibana/issues/185999 + it.skip('should send a successful request', async () => { + await PageObjects.console.addNewVariable({ name: 'query1', value: '{"match_all": {}}' }); + await PageObjects.console.monaco.enterText('\n GET _search\n'); + await PageObjects.console.monaco.enterText(`{\n\t"query": "\${query1}"`); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.try(async () => { + const status = await PageObjects.console.getResponseStatus(); + expect(status).to.eql(200); + }); + }); + }); + }); +}; diff --git a/test/functional/apps/console/monaco/_vector_tile.ts b/test/functional/apps/console/monaco/_vector_tile.ts new file mode 100644 index 0000000000000..4c00c5345c92f --- /dev/null +++ b/test/functional/apps/console/monaco/_vector_tile.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 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'console', 'header', 'home']); + const retry = getService('retry'); + const security = getService('security'); + + describe('console vector tiles response validation', function describeIndexTests() { + before(async () => { + await security.testUser.setRoles(['kibana_admin', 'kibana_sample_admin']); + await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { + useActualUrl: true, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.home.addSampleDataSet('logs'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.common.navigateToApp('console'); + await PageObjects.console.closeHelpIfExists(); + await PageObjects.console.monaco.clearEditorText(); + }); + + it('should validate response', async () => { + await PageObjects.console.monaco.enterText( + `GET kibana_sample_data_logs/_mvt/geo.coordinates/0/0/0` + ); + await PageObjects.console.clickPlay(); + await retry.try(async () => { + const actualResponse = await PageObjects.console.monaco.getOutputText(); + expect(actualResponse).to.contain('"meta": ['); + }); + }); + + after(async () => { + await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { + useActualUrl: true, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.home.removeSampleDataSet('logs'); + await security.testUser.restoreDefaults(); + }); + }); +} diff --git a/test/functional/apps/console/monaco/_xjson.ts b/test/functional/apps/console/monaco/_xjson.ts new file mode 100644 index 0000000000000..8f0a8d368ed06 --- /dev/null +++ b/test/functional/apps/console/monaco/_xjson.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getService, getPageObjects }: FtrProviderContext) => { + const retry = getService('retry'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + + describe('XJSON', function testXjson() { + this.tags('includeFirefox'); + before(async () => { + await PageObjects.common.navigateToApp('console'); + await PageObjects.console.closeHelpIfExists(); + }); + + beforeEach(async () => { + await PageObjects.console.monaco.clearEditorText(); + }); + + const executeRequest = async (request = '\n GET _search') => { + await PageObjects.console.monaco.enterText(request); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + }; + + describe('inline http request', () => { + it('should not have validation errors', async () => { + await PageObjects.console.monaco.enterText('\n GET foo/bar'); + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + }); + + it('should have validation error for invalid method', async () => { + await PageObjects.console.monaco.enterText('\n FOO foo/bar'); + // Retry because the error marker is not always immediately visible. + await retry.try(async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(true); + }); + }); + + it('should have validation error for invalid path', async () => { + await PageObjects.console.monaco.enterText('\n GET'); + // Retry because the error marker is not always immediately visible. + await retry.try(async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(true); + }); + }); + + it('should have validation error for invalid body', async () => { + await PageObjects.console.monaco.enterText('\n POST foo/bar\n {"foo": "bar"'); + // Retry because the error marker is not always immediately visible. + await retry.try(async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(true); + }); + }); + + it('should not trigger error for multiple bodies for _msearch requests', async () => { + await PageObjects.console.monaco.enterText( + '\nGET foo/_msearch \n{}\n{"query": {"match_all": {}}}\n{"index": "bar"}\n{"query": {"match_all": {}}}' + ); + // Retry until typing is finished. + await retry.try(async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + }); + }); + + it('should not trigger validation errors for multiple JSON blocks', async () => { + await PageObjects.console.monaco.enterText('\nPOST test/doc/1 \n{\n "foo": "bar"\n}'); + await PageObjects.console.monaco.enterText('\nPOST test/doc/2 \n{\n "foo": "baz"\n}'); + await PageObjects.console.monaco.enterText('\nPOST test/doc/3 \n{\n "foo": "qux"\n}'); + // Retry until typing is finished. + await retry.try(async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + }); + }); + + it('should allow escaping quotation mark by wrapping it in triple quotes', async () => { + await PageObjects.console.monaco.enterText( + '\nPOST test/_doc/1 \n{\n "foo": """look "escaped" quotes"""\n}' + ); + // Retry until typing is finished and validation errors are gone. + await retry.try(async () => { + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + }); + }); + + it('should allow inline comments in request url row', async () => { + await executeRequest('\n GET _search // inline comment'); + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + expect(await PageObjects.console.getResponseStatus()).to.eql(200); + }); + + it('should allow inline comments in request body', async () => { + await executeRequest( + '\n GET _search \n{\n "query": {\n "match_all": {} // inline comment\n}\n}' + ); + expect(await PageObjects.console.monaco.hasInvalidSyntax()).to.be(false); + expect(await PageObjects.console.getResponseStatus()).to.eql(200); + }); + + it('should print warning for deprecated request', async () => { + await executeRequest('\nGET .kibana'); + expect(await PageObjects.console.monaco.responseHasDeprecationWarning()).to.be(true); + }); + + it('should not print warning for non-deprecated request', async () => { + await executeRequest('\n GET _search'); + expect(await PageObjects.console.monaco.responseHasDeprecationWarning()).to.be(false); + }); + }); + }); +}; diff --git a/test/functional/apps/console/config.ts b/test/functional/apps/console/monaco/config.ts similarity index 87% rename from test/functional/apps/console/config.ts rename to test/functional/apps/console/monaco/config.ts index f295f1b826492..13fd8b21c9162 100644 --- a/test/functional/apps/console/config.ts +++ b/test/functional/apps/console/monaco/config.ts @@ -7,10 +7,10 @@ */ import { FtrConfigProviderContext } from '@kbn/test'; -import { configureHTTP2 } from '../../../common/configure_http2'; +import { configureHTTP2 } from '../../../../common/configure_http2'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); return configureHTTP2({ ...functionalConfig.getAll(), diff --git a/test/functional/apps/console/monaco/index.ts b/test/functional/apps/console/monaco/index.ts new file mode 100644 index 0000000000000..7274118daaafe --- /dev/null +++ b/test/functional/apps/console/monaco/index.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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const config = getService('config'); + + describe('console app', function () { + before(async function () { + await browser.setWindowSize(1300, 1100); + }); + if (config.get('esTestCluster.ccs')) { + loadTestFile(require.resolve('./_console_ccs')); + } else { + loadTestFile(require.resolve('./_console')); + loadTestFile(require.resolve('./_autocomplete')); + loadTestFile(require.resolve('./_vector_tile')); + loadTestFile(require.resolve('./_comments')); + loadTestFile(require.resolve('./_variables')); + loadTestFile(require.resolve('./_xjson')); + loadTestFile(require.resolve('./_misc_console_behavior')); + loadTestFile(require.resolve('./_context_menu')); + loadTestFile(require.resolve('./_text_input')); + loadTestFile(require.resolve('./_settings')); + } + }); +} diff --git a/test/functional/apps/dashboard_elements/controls/common/config.ts b/test/functional/apps/dashboard_elements/controls/common/config.ts index 60497ce2dae41..7e7e9ada1644d 100644 --- a/test/functional/apps/dashboard_elements/controls/common/config.ts +++ b/test/functional/apps/dashboard_elements/controls/common/config.ts @@ -17,5 +17,13 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { junit: { reportName: 'Dashboard Elements - Controls tests', }, + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + // disabling the monaco editor to run tests for ace + `--console.dev.enableMonaco=false`, + ], + }, }; } diff --git a/test/functional/apps/dashboard_elements/controls/options_list/config.ts b/test/functional/apps/dashboard_elements/controls/options_list/config.ts index c55987afa5570..150da945a1203 100644 --- a/test/functional/apps/dashboard_elements/controls/options_list/config.ts +++ b/test/functional/apps/dashboard_elements/controls/options_list/config.ts @@ -17,5 +17,13 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { junit: { reportName: 'Dashboard Elements - Controls Options List tests', }, + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + // disabling the monaco editor to run tests for ace + `--console.dev.enableMonaco=false`, + ], + }, }; } diff --git a/test/functional/config.ccs.ts b/test/functional/config.ccs.ts index cea1de2be8316..506f57c72d183 100644 --- a/test/functional/config.ccs.ts +++ b/test/functional/config.ccs.ts @@ -20,7 +20,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [ require.resolve('./apps/dashboard/group3'), require.resolve('./apps/discover/ccs_compatibility'), - require.resolve('./apps/console/_console_ccs'), + require.resolve('./apps/console/monaco/_console_ccs'), require.resolve('./apps/management/ccs_compatibility'), require.resolve('./apps/getting_started'), ], diff --git a/test/functional/firefox/console.config.ts b/test/functional/firefox/console.config.ts index 420eee1f438cb..96141382047d0 100644 --- a/test/functional/firefox/console.config.ts +++ b/test/functional/firefox/console.config.ts @@ -16,7 +16,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { ...baseConfig.getAll(), - testFiles: [require.resolve('../apps/console')], + testFiles: [require.resolve('../apps/console/monaco')], junit: { reportName: 'Firefox UI Functional Tests - Console', diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 3fdc1e8ab0f74..84267de85a595 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -18,6 +18,166 @@ export class ConsolePageObject extends FtrService { private readonly common = this.ctx.getPageObject('common'); private readonly browser = this.ctx.getService('browser'); + public monaco = { + getTextArea: async () => { + const codeEditor = await this.testSubjects.find('consoleMonacoEditor'); + return await codeEditor.findByTagName('textarea'); + }, + getEditorText: async () => { + const codeEditor = await this.testSubjects.find('consoleMonacoEditor'); + const editorViewDiv = await codeEditor.findByClassName('view-lines'); + return await editorViewDiv.getVisibleText(); + }, + getEditorTextAtLine: async (line: number) => { + const codeEditor = await this.testSubjects.find('consoleMonacoEditor'); + const editorViewDiv = await codeEditor.findAllByClassName('view-line'); + return await editorViewDiv[line].getVisibleText(); + }, + getCurrentLineNumber: async () => { + const textArea = await this.monaco.getTextArea(); + const styleAttribute = (await textArea.getAttribute('style')) ?? ''; + const height = parseFloat(styleAttribute.replace(/.*height: ([+-]?\d+(\.\d+)?).*/, '$1')); + const top = parseFloat(styleAttribute.replace(/.*top: ([+-]?\d+(\.\d+)?).*/, '$1')); + // calculate the line number by dividing the top position by the line height + // and adding 1 because line numbers start at 1 + return Math.ceil(top / height) + 1; + }, + clearEditorText: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.clickMouseButton(); + await textArea.clearValueWithKeyboard(); + }, + getOutputText: async () => { + const outputPanel = await this.testSubjects.find('consoleMonacoOutput'); + const outputViewDiv = await outputPanel.findByClassName('monaco-scrollable-element'); + return await outputViewDiv.getVisibleText(); + }, + pressEnter: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys(Key.ENTER); + }, + enterText: async (text: string) => { + const textArea = await this.monaco.getTextArea(); + await textArea.type(text); + }, + promptAutocomplete: async (letter = 'b') => { + const textArea = await this.monaco.getTextArea(); + await textArea.type(letter); + await this.retry.waitFor('autocomplete to be visible', () => + this.monaco.isAutocompleteVisible() + ); + }, + isAutocompleteVisible: async () => { + const element = await this.find.byClassName('suggest-widget').catch(() => null); + if (!element) return false; + + const attribute = await element.getAttribute('style'); + return !attribute?.includes('display: none;'); + }, + getAutocompleteSuggestion: async (index: number) => { + const suggestionsWidget = await this.find.byClassName('suggest-widget'); + const suggestions = await suggestionsWidget.findAllByClassName('monaco-list-row'); + const label = await suggestions[index].findByClassName('label-name'); + return label.getVisibleText(); + }, + pressUp: async (shift: boolean = false) => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.UP] : Key.UP); + }, + pressDown: async (shift: boolean = false) => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.DOWN] : Key.DOWN); + }, + pressRight: async (shift: boolean = false) => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.RIGHT] : Key.RIGHT); + }, + pressLeft: async (shift: boolean = false) => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.LEFT] : Key.LEFT); + }, + pressCtrlSpace: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([ + Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], + Key.SPACE, + ]); + }, + pressCtrlEnter: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([ + Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], + Key.ENTER, + ]); + }, + pressCtrlI: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'i']); + }, + pressCtrlUp: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([ + Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], + Key.UP, + ]); + }, + pressCtrlDown: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([ + Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], + Key.DOWN, + ]); + }, + pressCtrlL: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'l']); + }, + pressCtrlSlash: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], '/']); + }, + pressEscape: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys(Key.ESCAPE); + }, + selectAllRequests: async () => { + const textArea = await this.monaco.getTextArea(); + const selectionKey = Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL']; + await textArea.pressKeys([selectionKey, 'a']); + }, + getEditor: async () => { + return await this.testSubjects.find('consoleMonacoEditor'); + }, + hasInvalidSyntax: async () => { + return await this.find.existsByCssSelector('.squiggly-error'); + }, + responseHasDeprecationWarning: async () => { + const response = await this.monaco.getOutputText(); + return response.trim().startsWith('#!'); + }, + selectCurrentRequest: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.clickMouseButton(); + }, + getFontSize: async () => { + const codeEditor = await this.testSubjects.find('consoleMonacoEditor'); + const editorViewDiv = await codeEditor.findByClassName('view-line'); + return await editorViewDiv.getComputedStyle('font-size'); + }, + pasteClipboardValue: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'v']); + }, + copyRequestsToClipboard: async () => { + const textArea = await this.monaco.getTextArea(); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'a']); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'c']); + }, + isA11yOverlayVisible: async () => { + return await this.testSubjects.exists('codeEditorAccessibilityOverlay'); + }, + }; + public async getVisibleTextFromAceEditor(editor: WebElementWrapper) { const lines = await editor.findAllByClassName('ace_line_group'); const linesText = await Promise.all(lines.map(async (line) => await line.getVisibleText())); diff --git a/test/tsconfig.json b/test/tsconfig.json index 33a192fc996c6..0f120b831abe7 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -72,5 +72,6 @@ "@kbn/ftr-common-functional-ui-services", "@kbn/monaco", "@kbn/search-types", + "@kbn/console-plugin", ] } diff --git a/x-pack/test/functional/apps/reporting_management/config.ts b/x-pack/test/functional/apps/reporting_management/config.ts index d0d07ff200281..af7abdc5122e1 100644 --- a/x-pack/test/functional/apps/reporting_management/config.ts +++ b/x-pack/test/functional/apps/reporting_management/config.ts @@ -13,5 +13,13 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { ...functionalConfig.getAll(), testFiles: [require.resolve('.')], + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + // disabling the monaco editor to run tests for ace + `--console.dev.enableMonaco=false`, + ], + }, }; } From bdef3aed2bfab93070fb751f1913761bff0e593f Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 19 Jun 2024 08:57:00 -0700 Subject: [PATCH 122/127] [HTTP/OAS] Add makefile to oas_docs (#185911) --- oas_docs/.spectral.yaml | 103 + oas_docs/README.md | 4 + oas_docs/kibana.info.serverless.yaml | 47 + oas_docs/kibana.serverless.yaml | 7394 ++++++++++++++++++++++++++ oas_docs/makefile | 29 + 5 files changed, 7577 insertions(+) create mode 100644 oas_docs/.spectral.yaml create mode 100644 oas_docs/README.md create mode 100644 oas_docs/kibana.info.serverless.yaml create mode 100644 oas_docs/kibana.serverless.yaml create mode 100644 oas_docs/makefile diff --git a/oas_docs/.spectral.yaml b/oas_docs/.spectral.yaml new file mode 100644 index 0000000000000..b328e320e23eb --- /dev/null +++ b/oas_docs/.spectral.yaml @@ -0,0 +1,103 @@ +extends: ["spectral:oas"] +rules: +# Built-in rules + # Descriptions + oas3-parameter-description: warn + oas2-parameter-description: warn + tag-description: info + # Document info + info-contact: info + info-description: warn + info-license: warn + # Examples + oas3-valid-media-example: false + oas3-valid-schema-example: false + oas2-valid-media-example: false + # Operations + operation-operationId: false + operation-operationId-unique: false + operation-operationId-valid-in-url: false + operation-tag-defined: warn + operation-tags: warn + # Responses + operation-success-response: warn + # Schema + oas3-schema: error + oas2-schema: error + # Tags + openapi-tags: warn + openapi-tags-alphabetical: info + # Turn off some built-in rules + operation-description: false + operation-singular-tag: false +# Custom rules + # Descriptions + avoid-problematic-words: + description: Ban certain words from descriptions + message: "Use appropriate replacements for problematic terms" + severity: warn + given: "$..*.description" + then: + function: pattern + functionOptions: + notMatch: /(blacklist|whitelist|execute|kill)/i + # Examples + operation-success-examples: + formats: ["oas3_1"] + description: Response code 200 should have at least one example. + message: "Each response body should have a realistic example. It must not contain any sensitive or confidential data." + severity: info + given: $.paths[*].[*].responses.[200].content.[application/json] + then: + field: examples + function: defined + # Extensions + internal-extension: + description: Operations should not have x-internal extension. + message: "Do not publish x-internal operations" + severity: error + given: $.paths[*].[get,put,post,delete,options,head,patch,trace] + then: + field: x-internal + function: undefined + # Operations + operation-summary: + description: Operations should have summaries. + message: "Each operation should have a summary" + severity: error + recommended: true + given: $.paths[*].[get,put,post,delete,options,head,patch,trace] + then: + field: summary + function: defined + operation-summary-length: + description: Operation summary should be between 5 and 45 characters + given: "$.paths[*].[get,put,post,delete,options,head,patch,trace]" + then: + field: summary + function: length + functionOptions: + max: 45 + min: 5 + severity: warn + simple-verbs-in-summary: + given: + - "$.paths[*][*].summary" + then: + function: pattern + functionOptions: + notMatch: "Retrieve|Return|List *" + severity: warn + description: Summaries should use common verbs. + message: "Summaries should use common verbs like Get, Update, Delete whenever possible" + # NOTE: This one hiccups on acronyms so perhaps too noisy + # docs-operation-summary-sentence-case: + # description: Operation summary should be sentence cased + # given: "$.paths[*].[get,put,post,delete,options,head,patch,trace]" + # then: + # field: summary + # function: pattern + # functionOptions: + # match: /^[A-Z]+[^A-Z]+$/ + # severity: warn + diff --git a/oas_docs/README.md b/oas_docs/README.md new file mode 100644 index 0000000000000..70e39571c0af6 --- /dev/null +++ b/oas_docs/README.md @@ -0,0 +1,4 @@ +The `bundle.json` and `bundle.serverless.json` files are generated automatically. + +The `kibana.openapi.serverless.yaml` file is a temporary OpenAPI document created by joining some manually-maintained files. +To create it and lint it, run `make api-docs` and `make api-docs-lint`. \ No newline at end of file diff --git a/oas_docs/kibana.info.serverless.yaml b/oas_docs/kibana.info.serverless.yaml new file mode 100644 index 0000000000000..c96325cf7c75d --- /dev/null +++ b/oas_docs/kibana.info.serverless.yaml @@ -0,0 +1,47 @@ +openapi: 3.0.3 +info: + title: Kibana Serverless APIs + description: | + The Kibana REST APIs for Elastic serverless enable you to manage resources + such as connectors, data views, and saved objects. The API calls are + stateless. Each request that you make happens in isolation from other calls + and must include all of the necessary information for Kibana to fulfill the + request. API requests return JSON output, which is a format that is + machine-readable and works well for automation. + + To interact with Kibana APIs, use the following operations: + + - GET: Fetches the information. + - POST: Adds new information. + - PUT: Updates the existing information. + - DELETE: Removes the information. + + You can prepend any Kibana API endpoint with `kbn:` and run the request in + **Dev Tools → Console**. For example: + + ``` + GET kbn:/api/data_views + ``` + version: "1.0.2" + license: + name: Elastic License 2.0 + url: https://www.elastic.co/licensing/elastic-license + contact: + name: Kibana Team +# servers: +# - url: https://{kibana_url} +# variables: +# kibana_url: +# default: localhost:5601 +# security: +# - apiKeyAuth: [] +# components: +# securitySchemes: +# apiKeyAuth: +# type: apiKey +# in: header +# name: Authorization +# description: > +# These APIs use key-based authentication. +# You must create an API key and use the encoded value in the request header. +# For example: `Authorization: ApiKey base64AccessApiKey` \ No newline at end of file diff --git a/oas_docs/kibana.serverless.yaml b/oas_docs/kibana.serverless.yaml new file mode 100644 index 0000000000000..d7b5512e96099 --- /dev/null +++ b/oas_docs/kibana.serverless.yaml @@ -0,0 +1,7394 @@ +openapi: 3.0.3 +info: + title: Kibana Serverless APIs + description: | + The Kibana REST APIs for Elastic serverless enable you to manage resources + such as connectors, data views, and saved objects. The API calls are + stateless. Each request that you make happens in isolation from other calls + and must include all of the necessary information for Kibana to fulfill the + request. API requests return JSON output, which is a format that is + machine-readable and works well for automation. + + To interact with Kibana APIs, use the following operations: + + - GET: Fetches the information. + - POST: Adds new information. + - PUT: Updates the existing information. + - DELETE: Removes the information. + + You can prepend any Kibana API endpoint with `kbn:` and run the request in + **Dev Tools → Console**. For example: + + ``` + GET kbn:/api/data_views + ``` + version: 1.0.2 + license: + name: Elastic License 2.0 + url: https://www.elastic.co/licensing/elastic-license + contact: + name: Kibana Team +servers: + - url: https://{kibanaUrl} + variables: + kibanaUrl: + default: localhost:5601 + - url: https://{kibana_url} + variables: + kibana_url: + default: localhost:5601 + - url: / +tags: + - name: APM agent keys + description: > + Configure APM agent keys to authorize requests from APM agents to the APM + Server. + x-displayName: APM agent keys + - name: APM annotations + description: > + Annotate visualizations in the APM app with significant events. + Annotations enable you to easily see how events are impacting the + performance of your applications. + x-displayName: APM annotations + - name: connectors + description: Connector APIs enable you to create and manage connectors. + x-displayName: connectors + - name: data views + description: >- + Data view APIs enable you to manage data views, formerly known as Kibana + index patterns. + x-displayName: data views + - name: ml + description: Machine learning + x-displayName: ml + - name: saved objects + description: >- + Manage Kibana saved objects, including dashboards, visualizations, and + more. + x-displayName: saved objects +paths: + /api/apm/agent_keys: + post: + summary: Create an APM agent key + description: Create a new agent key for APM. + tags: + - APM agent keys + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + privileges: + type: array + items: + type: string + enum: + - event:write + - config_agent:read + responses: + '200': + description: Agent key created successfully + content: + application/json: + schema: + type: object + properties: + api_key: + type: string + expiration: + type: integer + format: int64 + id: + type: string + name: + type: string + encoded: + type: string + /api/apm/services/{serviceName}/annotation/search: + get: + summary: Search for annotations + description: Search for annotations related to a specific service. + tags: + - APM annotations + parameters: + - name: serviceName + in: path + required: true + description: The name of the service + schema: + type: string + - name: environment + in: query + required: false + description: The environment to filter annotations by + schema: + type: string + - name: start + in: query + required: false + description: The start date for the search + schema: + type: string + - name: end + in: query + required: false + description: The end date for the search + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + annotations: + type: array + items: + type: object + properties: + type: + type: string + enum: + - version + id: + type: string + '@timestamp': + type: number + text: + type: string + /api/apm/services/{serviceName}/annotation: + post: + summary: Create a service annotation + description: Create a new annotation for a specific service. + tags: + - APM annotations + parameters: + - name: serviceName + in: path + required: true + description: The name of the service + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + '@timestamp': + type: string + service: + type: object + properties: + version: + type: string + environment: + type: string + message: + type: string + tags: + type: array + items: + type: string + responses: + '200': + description: Annotation created successfully + content: + application/json: + schema: + type: object + properties: + _id: + type: string + _index: + type: string + _source: + type: object + properties: + annotation: + type: string + tags: + type: array + items: + type: string + message: + type: string + service: + type: object + properties: + name: + type: string + environment: + type: string + version: + type: string + event: + type: object + properties: + created: + type: string + '@timestamp': + type: string + /api/actions/connector: + post: + summary: Create a connector + operationId: createConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/Connectors_kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_create_connector_request' + examples: + createEmailConnectorRequest: + $ref: >- + #/components/examples/Connectors_create_email_connector_request + createIndexConnectorRequest: + $ref: >- + #/components/examples/Connectors_create_index_connector_request + createWebhookConnectorRequest: + $ref: >- + #/components/examples/Connectors_create_webhook_connector_request + createXmattersConnectorRequest: + $ref: >- + #/components/examples/Connectors_create_xmatters_connector_request + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_connector_response_properties' + examples: + createEmailConnectorResponse: + $ref: >- + #/components/examples/Connectors_create_email_connector_response + createIndexConnectorResponse: + $ref: >- + #/components/examples/Connectors_create_index_connector_response + createWebhookConnectorResponse: + $ref: >- + #/components/examples/Connectors_create_webhook_connector_response + createXmattersConnectorResponse: + $ref: >- + #/components/examples/Connectors_create_xmatters_connector_response + '401': + $ref: '#/components/responses/Connectors_401' + security: + - Connectors_apiKeyAuth: [] + /api/actions/connector/{connectorId}: + get: + summary: Get a connector information + operationId: getConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/Connectors_connector_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_connector_response_properties' + examples: + getConnectorResponse: + $ref: '#/components/examples/Connectors_get_connector_response' + '401': + $ref: '#/components/responses/Connectors_401' + '404': + $ref: '#/components/responses/Connectors_404' + security: + - Connectors_apiKeyAuth: [] + delete: + summary: Delete a connector + operationId: deleteConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/Connectors_kbn_xsrf' + - $ref: '#/components/parameters/Connectors_connector_id' + responses: + '204': + description: Indicates a successful call. + '401': + $ref: '#/components/responses/Connectors_401' + '404': + $ref: '#/components/responses/Connectors_404' + security: + - Connectors_apiKeyAuth: [] + post: + summary: Create a connector + operationId: createConnectorId + tags: + - connectors + parameters: + - $ref: '#/components/parameters/Connectors_kbn_xsrf' + - in: path + name: connectorId + description: > + A UUID v1 or v4 identifier for the connector. If you omit this + parameter, an identifier is randomly generated. + required: true + schema: + type: string + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_create_connector_request' + examples: + createIndexConnectorRequest: + $ref: >- + #/components/examples/Connectors_create_index_connector_request + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_connector_response_properties' + examples: + createIndexConnectorResponse: + $ref: >- + #/components/examples/Connectors_create_index_connector_response + '401': + $ref: '#/components/responses/Connectors_401' + security: + - Connectors_apiKeyAuth: [] + put: + summary: Update a connector + operationId: updateConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/Connectors_kbn_xsrf' + - $ref: '#/components/parameters/Connectors_connector_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_update_connector_request' + examples: + updateIndexConnectorRequest: + $ref: >- + #/components/examples/Connectors_update_index_connector_request + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Connectors_connector_response_properties' + '400': + $ref: '#/components/responses/Connectors_401' + '401': + $ref: '#/components/responses/Connectors_401' + '404': + $ref: '#/components/responses/Connectors_404' + security: + - Connectors_apiKeyAuth: [] + /api/actions/connectors: + get: + summary: Get all connectors + operationId: getConnectors + tags: + - connectors + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: array + items: + $ref: >- + #/components/schemas/Connectors_connector_response_properties + examples: + getConnectorsResponse: + $ref: '#/components/examples/Connectors_get_connectors_response' + '401': + $ref: '#/components/responses/Connectors_401' + security: + - Connectors_apiKeyAuth: [] + /api/actions/connector_types: + get: + summary: Get all connector types + operationId: getConnectorTypes + tags: + - connectors + parameters: + - in: query + name: feature_id + description: >- + A filter to limit the retrieved connector types to those that + support a specific feature (such as alerting or cases). + schema: + $ref: '#/components/schemas/Connectors_features' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + title: Get connector types response body properties + description: The properties vary for each connector type. + type: array + items: + type: object + properties: + enabled: + type: boolean + description: >- + Indicates whether the connector type is enabled in + Kibana. + example: true + enabled_in_config: + type: boolean + description: >- + Indicates whether the connector type is enabled in the + Kibana configuration file. + example: true + enabled_in_license: + type: boolean + description: >- + Indicates whether the connector is enabled in the + license. + example: true + id: + $ref: '#/components/schemas/Connectors_connector_types' + is_system_action_type: + type: boolean + example: false + minimum_license_required: + type: string + description: The license that is required to use the connector type. + example: basic + name: + type: string + description: The name of the connector type. + example: Index + supported_feature_ids: + type: array + description: The features that are supported by the connector type. + items: + $ref: '#/components/schemas/Connectors_features' + example: + - alerting + - cases + - siem + examples: + getConnectorTypesServerlessResponse: + $ref: >- + #/components/examples/Connectors_get_connector_types_generativeai_response + '401': + $ref: '#/components/responses/Connectors_401' + security: + - Connectors_apiKeyAuth: [] + /s/{spaceId}/api/data_views: + get: + summary: Get all data views + operationId: getAllDataViews + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_space_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + namespaces: + type: array + items: + type: string + title: + type: string + typeMeta: + type: object + examples: + getAllDataViewsResponse: + $ref: '#/components/examples/Data_views_get_data_views_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /s/{spaceId}/api/data_views/data_view: + post: + summary: Create a data view + operationId: createDataView + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_space_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_create_data_view_request_object' + examples: + createDataViewRequest: + $ref: '#/components/examples/Data_views_create_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_data_view_response_object' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /s/{spaceId}/api/data_views/data_view/{viewId}: + get: + summary: Get a data view + operationId: getDataView + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_data_view_response_object' + examples: + getDataViewResponse: + $ref: '#/components/examples/Data_views_get_data_view_response' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + delete: + summary: Delete a data view + operationId: deleteDataView + description: > + WARNING: When you delete a data view, it cannot be recovered. This + functionality is in technical preview and may be changed or removed in a + future release. Elastic will work to fix any issues, but features in + technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + responses: + '204': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + post: + summary: Update a data view + operationId: updateDataView + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_update_data_view_request_object' + examples: + updateDataViewRequest: + $ref: '#/components/examples/Data_views_update_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_data_view_response_object' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /s/{spaceId}/api/data_views/default: + get: + summary: Get the default data view identifier + operationId: getDefaultDataView + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_space_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view_id: + type: string + examples: + getDefaultDataViewResponse: + $ref: >- + #/components/examples/Data_views_get_default_data_view_response + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + post: + summary: Sets the default data view identifier + operationId: setDefaultDatailView + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_space_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - data_view_id + properties: + data_view_id: + type: string + nullable: true + description: > + The data view identifier. NOTE: The API does not validate + whether it is a valid identifier. Use `null` to unset the + default data view. + force: + type: boolean + description: Update an existing default data view identifier. + default: false + examples: + setDefaultDataViewRequest: + $ref: '#/components/examples/Data_views_set_default_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /s/{spaceId}/api/data_views/data_view/{viewId}/fields: + post: + summary: Update data view fields metadata + operationId: updateFieldsMetadata + description: > + Update fields presentation metadata such as count, customLabel and + format. This functionality is in technical preview and may be changed or + removed in a future release. Elastic will work to fix any issues, but + features in technical preview are not subject to the support SLA of + official GA features. You can update multiple fields in one request. + Updates are merged with persisted metadata. To remove existing metadata, + specify null as the value. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - fields + properties: + fields: + description: The field object. + type: object + examples: + updateFieldsMetadataRequest: + $ref: '#/components/examples/Data_views_update_field_metadata_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field: + post: + summary: Create a runtime field + operationId: createRuntimeField + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + createRuntimeFieldRequest: + $ref: '#/components/examples/Data_views_create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + put: + summary: Create or update a runtime field + operationId: createUpdateRuntimeField + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_space_id' + - name: viewId + in: path + description: | + The ID of the data view fields you want to update. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + updateRuntimeFieldRequest: + $ref: '#/components/examples/Data_views_create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /s/{spaceId}/api/data_views/data_view/{viewId}/runtime_field/{fieldName}: + get: + summary: Get a runtime field + operationId: getRuntimeField + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_field_name' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + examples: + getRuntimeFieldResponse: + $ref: '#/components/examples/Data_views_get_runtime_field_response' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + delete: + summary: Delete a runtime field from a data view + operationId: deleteRuntimeField + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_field_name' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + responses: + '200': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + post: + summary: Update a runtime field + operationId: updateRuntimeField + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_field_name' + - $ref: '#/components/parameters/Data_views_view_id' + - $ref: '#/components/parameters/Data_views_space_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - runtimeField + properties: + runtimeField: + type: object + description: | + The runtime field definition object. + + You can update following fields: + + - `type` + - `script` + examples: + updateRuntimeFieldRequest: + $ref: '#/components/examples/Data_views_update_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views: + get: + summary: Get all data views in the default space + operationId: getAllDataViewsDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + namespaces: + type: array + items: + type: string + title: + type: string + typeMeta: + type: object + examples: + getAllDataViewsResponse: + $ref: '#/components/examples/Data_views_get_data_views_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views/data_view: + post: + summary: Create a data view in the default space + operationId: createDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_create_data_view_request_object' + examples: + createDataViewRequest: + $ref: '#/components/examples/Data_views_create_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_data_view_response_object' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views/data_view/{viewId}: + get: + summary: Get a data view in the default space + operationId: getDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_view_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_data_view_response_object' + examples: + getDataViewResponse: + $ref: '#/components/examples/Data_views_get_data_view_response' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + delete: + summary: Delete a data view from the default space + operationId: deleteDataViewDefault + description: > + WARNING: When you delete a data view, it cannot be recovered. This + functionality is in technical preview and may be changed or removed in a + future release. Elastic will work to fix any issues, but features in + technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + responses: + '204': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + post: + summary: Update a data view in the default space + operationId: updateDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_update_data_view_request_object' + examples: + updateDataViewRequest: + $ref: '#/components/examples/Data_views_update_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_data_view_response_object' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views/data_view/{viewId}/fields: + post: + summary: Update data view fields metadata in the default space + operationId: updateFieldsMetadataDefault + description: > + Update fields presentation metadata such as count, customLabel and + format. This functionality is in technical preview and may be changed or + removed in a future release. Elastic will work to fix any issues, but + features in technical preview are not subject to the support SLA of + official GA features. You can update multiple fields in one request. + Updates are merged with persisted metadata. To remove existing metadata, + specify null as the value. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - fields + properties: + fields: + description: The field object. + type: object + examples: + updateFieldsMetadataRequest: + $ref: '#/components/examples/Data_views_update_field_metadata_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views/data_view/{viewId}/runtime_field: + post: + summary: Create a runtime field in the default space + operationId: createRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - $ref: '#/components/parameters/Data_views_view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + createRuntimeFieldRequest: + $ref: '#/components/examples/Data_views_create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + put: + summary: Create or update a runtime field in the default space + operationId: createUpdateRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + - name: viewId + in: path + description: | + The ID of the data view fields you want to update. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - runtimeField + properties: + name: + type: string + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. + examples: + updateRuntimeFieldRequest: + $ref: '#/components/examples/Data_views_create_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views/data_view/{viewId}/runtime_field/{fieldName}: + get: + summary: Get a runtime field in the default space + operationId: getRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_field_name' + - $ref: '#/components/parameters/Data_views_view_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view: + type: object + fields: + type: array + items: + type: object + examples: + getRuntimeFieldResponse: + $ref: '#/components/examples/Data_views_get_runtime_field_response' + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + delete: + summary: Delete a runtime field from a data view in the default space + operationId: deleteRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_field_name' + - $ref: '#/components/parameters/Data_views_view_id' + responses: + '200': + description: Indicates a successful call. + '404': + description: Object is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_404_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + post: + summary: Update a runtime field in the default space + operationId: updateRuntimeFieldDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_field_name' + - $ref: '#/components/parameters/Data_views_view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - runtimeField + properties: + runtimeField: + type: object + description: | + The runtime field definition object. + + You can update following fields: + + - `type` + - `script` + examples: + updateRuntimeFieldRequest: + $ref: '#/components/examples/Data_views_update_runtime_field_request' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/data_views/default: + get: + summary: Get the default data view in the default space + operationId: getDefaultDataViewDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + data_view_id: + type: string + examples: + getDefaultDataViewResponse: + $ref: >- + #/components/examples/Data_views_get_default_data_view_response + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + post: + summary: Set the default data view in the default space + operationId: setDefaultDatailViewDefault + description: > + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - data views + parameters: + - $ref: '#/components/parameters/Data_views_kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - data_view_id + properties: + data_view_id: + type: string + nullable: true + description: > + The data view identifier. NOTE: The API does not validate + whether it is a valid identifier. Use `null` to unset the + default data view. + force: + type: boolean + description: Update an existing default data view identifier. + default: false + examples: + setDefaultDataViewRequest: + $ref: '#/components/examples/Data_views_set_default_data_view_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Data_views_400_response' + security: + - Data_views_basicAuth: [] + - Data_views_apiKeyAuth: [] + /api/ml/saved_objects/sync: + get: + summary: Sync machine learning saved objects + description: > + Synchronizes Kibana saved objects for machine learning jobs and trained + models. This API runs automatically when you start Kibana and + periodically thereafter. + operationId: mlSync + tags: + - ml + parameters: + - $ref: '#/components/parameters/Machine_learning_APIs_simulateParam' + responses: + '200': + description: Indicates a successful call + content: + application/json: + schema: + $ref: '#/components/schemas/Machine_learning_APIs_mlSync200Response' + examples: + syncExample: + $ref: '#/components/examples/Machine_learning_APIs_mlSyncExample' + '401': + description: Authorization information is missing or invalid. + content: + application/json: + schema: + $ref: '#/components/schemas/Machine_learning_APIs_mlSync4xxResponse' + security: + - Machine_learning_APIs_apiKeyAuth: [] + /api/saved_objects/_export: + post: + summary: Export saved objects in the default space + operationId: exportSavedObjectsDefault + description: > + Retrieve sets of saved objects that you want to import into Kibana. + + You must include `type` or `objects` in the request body. + + + NOTE: The `savedObjects.maxImportExportSize` configuration setting + limits the number of saved objects which may be exported. + + + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/Serverless_saved_objects_kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + excludeExportDetails: + description: Do not add export details entry at the end of the stream. + type: boolean + default: false + includeReferencesDeep: + description: >- + Includes all of the referenced objects in the exported + objects. + type: boolean + objects: + description: A list of objects to export. + type: array + items: + type: object + type: + description: >- + The saved object types to include in the export. Use `*` to + export all the types. + oneOf: + - type: string + - type: array + items: + type: string + examples: + exportSavedObjectsRequest: + $ref: >- + #/components/examples/Serverless_saved_objects_export_objects_request + responses: + '200': + description: Indicates a successful call. + content: + application/x-ndjson: + schema: + type: object + additionalProperties: true + examples: + exportSavedObjectsResponse: + $ref: >- + #/components/examples/Serverless_saved_objects_export_objects_response + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/Serverless_saved_objects_400_response' + security: + - Serverless_saved_objects_apiKeyAuth: [] + /api/saved_objects/_import: + post: + summary: Import saved objects in the default space + operationId: importSavedObjectsDefault + description: > + Create sets of Kibana saved objects from a file created by the export + API. + + Saved objects can be imported only into the same version, a newer minor + on the same major, or the next major. Exported saved objects are not + backwards compatible and cannot be imported into an older version of + Kibana. + + + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/Serverless_saved_objects_kbn_xsrf' + - in: query + name: createNewCopies + schema: + type: boolean + required: false + description: > + Creates copies of saved objects, regenerates each object ID, and + resets the origin. When used, potential conflict errors are avoided. + NOTE: This option cannot be used with the `overwrite` and + `compatibilityMode` options. + - in: query + name: overwrite + schema: + type: boolean + required: false + description: > + Overwrites saved objects when they already exist. When used, + potential conflict errors are automatically resolved by overwriting + the destination object. NOTE: This option cannot be used with the + `createNewCopies` option. + - in: query + name: compatibilityMode + schema: + type: boolean + required: false + description: > + Applies various adjustments to the saved objects that are being + imported to maintain compatibility between different Kibana + versions. Use this option only if you encounter issues with imported + saved objects. NOTE: This option cannot be used with the + `createNewCopies` option. + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + description: > + A file exported using the export API. NOTE: The + `savedObjects.maxImportExportSize` configuration setting + limits the number of saved objects which may be included in + this file. Similarly, the + `savedObjects.maxImportPayloadBytes` setting limits the + overall size of the file that can be imported. + examples: + importObjectsRequest: + $ref: >- + #/components/examples/Serverless_saved_objects_import_objects_request + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: > + Indicates when the import was successfully completed. When + set to false, some objects may not have been created. For + additional information, refer to the `errors` and + `successResults` properties. + successCount: + type: integer + description: Indicates the number of successfully imported records. + errors: + type: array + items: + type: object + description: > + Indicates the import was unsuccessful and specifies the + objects that failed to import. + + + NOTE: One object may result in multiple errors, which + requires separate steps to resolve. For instance, a + `missing_references` error and conflict error. + successResults: + type: array + items: + type: object + description: > + Indicates the objects that are successfully imported, with + any metadata if applicable. + + + NOTE: Objects are created only when all resolvable errors + are addressed, including conflicts and missing references. + If objects are created as new copies, each entry in the + `successResults` array includes a `destinationId` + attribute. + examples: + importObjectsResponse: + $ref: >- + #/components/examples/Serverless_saved_objects_import_objects_response + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/Serverless_saved_objects_400_response' + security: + - Serverless_saved_objects_apiKeyAuth: [] + /s/{spaceId}/api/saved_objects/_export: + post: + summary: Export saved objects + operationId: exportSavedObjects + description: > + Retrieves sets of saved objects that you want to import into Kibana. + + You must include `type` or `objects` in the request body. + + + NOTE: The `savedObjects.maxImportExportSize` configuration setting + limits the number of saved objects which may be exported. + + + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/Serverless_saved_objects_kbn_xsrf' + - $ref: '#/components/parameters/Serverless_saved_objects_space_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: >- + #/components/schemas/Serverless_saved_objects_export_objects_request + examples: + exportSavedObjectsRequest: + $ref: >- + #/components/examples/Serverless_saved_objects_export_objects_request + responses: + '200': + description: Indicates a successful call. + content: + application/x-ndjson: + schema: + type: object + additionalProperties: true + examples: + exportSavedObjectsResponse: + $ref: >- + #/components/examples/Serverless_saved_objects_export_objects_response + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/Serverless_saved_objects_400_response' + security: + - Serverless_saved_objects_apiKeyAuth: [] + /s/{spaceId}/api/saved_objects/_import: + post: + summary: Import saved objects + operationId: importSavedObjects + description: > + Creates sets of Kibana saved objects from a file created by the export + API. + + Saved objects can be imported only into the same version, a newer minor + on the same major, or the next major. Exported saved objects are not + backwards compatible and cannot be imported into an older version of + Kibana. + + + This functionality is in technical preview and may be changed or removed + in a future release. Elastic will work to fix any issues, but features + in technical preview are not subject to the support SLA of official GA + features. + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/Serverless_saved_objects_kbn_xsrf' + - $ref: '#/components/parameters/Serverless_saved_objects_space_id' + - $ref: '#/components/parameters/Serverless_saved_objects_compatibility_mode' + - $ref: '#/components/parameters/Serverless_saved_objects_create_new_copies' + - $ref: '#/components/parameters/Serverless_saved_objects_overwrite' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: >- + #/components/schemas/Serverless_saved_objects_import_objects_request + examples: + importObjectsRequest: + $ref: >- + #/components/examples/Serverless_saved_objects_import_objects_request + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: >- + #/components/schemas/Serverless_saved_objects_200_import_objects_response + examples: + importObjectsResponse: + $ref: >- + #/components/examples/Serverless_saved_objects_import_objects_response + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/Serverless_saved_objects_400_response' + security: + - Serverless_saved_objects_apiKeyAuth: [] +components: + securitySchemes: + Connectors_apiKeyAuth: + type: apiKey + in: header + name: Authorization + description: > + Serverless APIs support only key-based authentication. You must create + an API key and use the encoded value in the request header. For example: + 'Authorization: ApiKey base64AccessApiKey'. + Data_views_basicAuth: + type: http + scheme: basic + Data_views_apiKeyAuth: + type: apiKey + in: header + name: Authorization + description: > + Serverless APIs support only key-based authentication. You must create + an API key and use the encoded value in the request header. For example: + 'Authorization: ApiKey base64AccessApiKey'. + Machine_learning_APIs_apiKeyAuth: + type: apiKey + in: header + name: ApiKey + Serverless_saved_objects_apiKeyAuth: + type: apiKey + in: header + name: Authorization + description: > + Serverless APIs support only key-based authentication. You must create + an API key and use the encoded value in the request header. For example: + 'Authorization: ApiKey base64AccessApiKey'. + parameters: + Connectors_kbn_xsrf: + schema: + type: string + in: header + name: kbn-xsrf + description: Cross-site request forgery protection + required: true + Connectors_connector_id: + in: path + name: connectorId + description: An identifier for the connector. + required: true + schema: + type: string + example: df770e30-8b8b-11ed-a780-3b746c987a81 + Data_views_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 + Data_views_kbn_xsrf: + schema: + type: string + in: header + name: kbn-xsrf + description: Cross-site request forgery protection + required: true + Data_views_view_id: + in: path + name: viewId + description: An identifier for the data view. + required: true + schema: + type: string + example: ff959d40-b880-11e8-a6d9-e546fe2bba5f + Data_views_field_name: + in: path + name: fieldName + description: The name of the runtime field. + required: true + schema: + type: string + example: hour_of_day + Machine_learning_APIs_simulateParam: + in: query + name: simulate + description: >- + When true, simulates the synchronization by returning only the list of + actions that would be performed. + required: false + schema: + type: boolean + example: 'true' + Serverless_saved_objects_kbn_xsrf: + schema: + type: string + in: header + name: kbn-xsrf + description: Cross-site request forgery protection + required: true + Serverless_saved_objects_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 + Serverless_saved_objects_compatibility_mode: + in: query + name: compatibilityMode + schema: + type: boolean + required: false + description: > + Applies various adjustments to the saved objects that are being imported + to maintain compatibility between different Kibana versions. Use this + option only if you encounter issues with imported saved objects. NOTE: + This option cannot be used with the `createNewCopies` option. + Serverless_saved_objects_create_new_copies: + in: query + name: createNewCopies + schema: + type: boolean + required: false + description: > + Creates copies of saved objects, regenerates each object ID, and resets + the origin. When used, potential conflict errors are avoided. NOTE: This + option cannot be used with the `overwrite` and `compatibilityMode` + options. + Serverless_saved_objects_overwrite: + in: query + name: overwrite + schema: + type: boolean + required: false + description: > + Overwrites saved objects when they already exist. When used, potential + conflict errors are automatically resolved by overwriting the + destination object. NOTE: This option cannot be used with the + `createNewCopies` option. + schemas: + Connectors_create_connector_request_bedrock: + title: Create Amazon Bedrock connector request + description: >- + The Amazon Bedrock connector uses axios to send a POST request to Amazon + Bedrock. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_bedrock' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + example: .bedrock + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_bedrock' + Connectors_create_connector_request_gemini: + title: Create Google Gemini connector request + description: >- + The Google Gemini connector uses axios to send a POST request to Google + Gemini. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_gemini' + connector_type_id: + type: string + description: The type of connector. + enum: + - .gemini + example: .gemini + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_gemini' + Connectors_create_connector_request_cases_webhook: + title: Create Webhook - Case Managment connector request + description: > + The Webhook - Case Management connector uses axios to send POST, PUT, + and GET requests to a case management RESTful API web service. + type: object + required: + - config + - connector_type_id + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_cases_webhook' + connector_type_id: + type: string + description: The type of connector. + enum: + - .cases-webhook + example: .cases-webhook + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_cases_webhook' + Connectors_create_connector_request_d3security: + title: Create D3 Security connector request + description: > + The connector uses axios to send a POST request to a D3 Security + endpoint. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_d3security' + connector_type_id: + type: string + description: The type of connector. + enum: + - .d3security + example: .d3security + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_d3security' + Connectors_create_connector_request_email: + title: Create email connector request + description: > + The email connector uses the SMTP protocol to send mail messages, using + an integration of Nodemailer. An exception is Microsoft Exchange, which + uses HTTP protocol for sending emails, Send mail. Email message text is + sent as both plain text and html text. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_email' + connector_type_id: + type: string + description: The type of connector. + enum: + - .email + example: .email + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_email' + Connectors_create_connector_request_genai: + title: Create OpenAI connector request + description: > + The OpenAI connector uses axios to send a POST request to either OpenAI + or Azure OpenAPI. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_genai' + connector_type_id: + type: string + description: The type of connector. + enum: + - .gen-ai + example: .gen-ai + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_genai' + Connectors_create_connector_request_index: + title: Create index connector request + description: The index connector indexes a document into Elasticsearch. + type: object + required: + - config + - connector_type_id + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_index' + connector_type_id: + type: string + description: The type of connector. + enum: + - .index + example: .index + name: + type: string + description: The display name for the connector. + example: my-connector + Connectors_create_connector_request_jira: + title: Create Jira connector request + description: The Jira connector uses the REST API v2 to create Jira issues. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_jira' + connector_type_id: + type: string + description: The type of connector. + enum: + - .jira + example: .jira + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_jira' + Connectors_create_connector_request_opsgenie: + title: Create Opsgenie connector request + description: The Opsgenie connector uses the Opsgenie alert API. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_opsgenie' + connector_type_id: + type: string + description: The type of connector. + enum: + - .opsgenie + example: .opsgenie + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_opsgenie' + Connectors_create_connector_request_pagerduty: + title: Create PagerDuty connector request + description: > + The PagerDuty connector uses the v2 Events API to trigger, acknowledge, + and resolve PagerDuty alerts. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_pagerduty' + connector_type_id: + type: string + description: The type of connector. + enum: + - .pagerduty + example: .pagerduty + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_pagerduty' + Connectors_create_connector_request_resilient: + title: Create IBM Resilient connector request + description: >- + The IBM Resilient connector uses the RESILIENT REST v2 to create IBM + Resilient incidents. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_resilient' + connector_type_id: + description: The type of connector. + type: string + example: .resilient + enum: + - .resilient + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_resilient' + Connectors_create_connector_request_sentinelone: + title: Create SentinelOne connector request + description: > + The SentinelOne connector communicates with SentinelOne Management + Console via REST API. This functionality is in technical preview and may + be changed or removed in a future release. Elastic will work to fix any + issues, but features in technical preview are not subject to the support + SLA of official GA features. + x-technical-preview: true + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_sentinelone' + connector_type_id: + type: string + description: The type of connector. + enum: + - .sentinelone + example: .sentinelone + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_sentinelone' + Connectors_create_connector_request_serverlog: + title: Create server log connector request + description: This connector writes an entry to the Kibana server log. + type: object + required: + - connector_type_id + - name + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .server-log + example: .server-log + name: + type: string + description: The display name for the connector. + example: my-connector + Connectors_create_connector_request_servicenow: + title: Create ServiceNow ITSM connector request + description: > + The ServiceNow ITSM connector uses the import set API to create + ServiceNow incidents. You can use the connector for rule actions and + cases. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow + example: .servicenow + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_servicenow' + Connectors_create_connector_request_servicenow_itom: + title: Create ServiceNow ITOM connector request + description: > + The ServiceNow ITOM connector uses the event API to create ServiceNow + events. You can use the connector for rule actions. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow_itom' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-itom + example: .servicenow-itom + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_servicenow' + Connectors_create_connector_request_servicenow_sir: + title: Create ServiceNow SecOps connector request + description: > + The ServiceNow SecOps connector uses the import set API to create + ServiceNow security incidents. You can use the connector for rule + actions and cases. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-sir + example: .servicenow-sir + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_servicenow' + Connectors_create_connector_request_slack_api: + title: Create Slack connector request + description: The Slack connector uses an API method to send Slack messages. + type: object + required: + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_slack_api' + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack_api + example: .slack_api + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_slack_api' + Connectors_create_connector_request_slack_webhook: + title: Create Slack connector request + description: The Slack connector uses Slack Incoming Webhooks. + type: object + required: + - connector_type_id + - name + - secrets + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack + example: .slack + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_slack_webhook' + Connectors_create_connector_request_swimlane: + title: Create Swimlane connector request + description: >- + The Swimlane connector uses the Swimlane REST API to create Swimlane + records. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_swimlane' + connector_type_id: + type: string + description: The type of connector. + enum: + - .swimlane + example: .swimlane + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_swimlane' + Connectors_create_connector_request_teams: + title: Create Microsoft Teams connector request + description: The Microsoft Teams connector uses Incoming Webhooks. + type: object + required: + - connector_type_id + - name + - secrets + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .teams + example: .teams + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_teams' + Connectors_create_connector_request_tines: + title: Create Tines connector request + description: > + The Tines connector uses Tines Webhook actions to send events via POST + request. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_tines' + connector_type_id: + type: string + description: The type of connector. + enum: + - .tines + example: .tines + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_tines' + Connectors_create_connector_request_torq: + title: Create Torq connector request + description: > + The Torq connector uses a Torq webhook to trigger workflows with Kibana + actions. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_torq' + connector_type_id: + type: string + description: The type of connector. + enum: + - .torq + example: .torq + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_torq' + Connectors_create_connector_request_webhook: + title: Create Webhook connector request + description: > + The Webhook connector uses axios to send a POST or PUT request to a web + service. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_webhook' + connector_type_id: + type: string + description: The type of connector. + enum: + - .webhook + example: .webhook + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_webhook' + Connectors_create_connector_request_xmatters: + title: Create xMatters connector request + description: > + The xMatters connector uses the xMatters Workflow for Elastic to send + actionable alerts to on-call xMatters resources. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_xmatters' + connector_type_id: + type: string + description: The type of connector. + enum: + - .xmatters + example: .xmatters + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_xmatters' + Connectors_config_properties_bedrock: + title: Connector request properties for an Amazon Bedrock connector + description: Defines properties for connectors when type is `.bedrock`. + type: object + required: + - apiUrl + properties: + apiUrl: + type: string + description: The Amazon Bedrock request URL. + defaultModel: + type: string + description: > + The generative artificial intelligence model for Amazon Bedrock to + use. Current support is for the Anthropic Claude models. + default: anthropic.claude-3-sonnet-20240229-v1:0 + Connectors_secrets_properties_bedrock: + title: Connector secrets properties for an Amazon Bedrock connector + description: Defines secrets for connectors when type is `.bedrock`. + type: object + required: + - accessKey + - secret + properties: + accessKey: + type: string + description: The AWS access key for authentication. + secret: + type: string + description: The AWS secret for authentication. + Connectors_config_properties_gemini: + title: Connector request properties for an Google Gemini connector + description: Defines properties for connectors when type is `.gemini`. + type: object + required: + - apiUrl + - gcpRegion + - gcpProjectID + properties: + apiUrl: + type: string + description: The Google Gemini request URL. + defaultModel: + type: string + description: >- + The generative artificial intelligence model for Google Gemini to + use. + default: gemini-1.5-pro-preview-0409 + gcpRegion: + type: string + description: The GCP region where the Vertex AI endpoint enabled. + gcpProjectID: + type: string + description: The Google ProjectID that has Vertex AI endpoint enabled. + Connectors_secrets_properties_gemini: + title: Connector secrets properties for a Google Gemini connector + description: Defines secrets for connectors when type is `.gemini`. + type: object + required: + - credentialsJSON + properties: + credentialsJSON: + type: string + description: >- + The service account credentials JSON file. The service account + should have Vertex AI user IAM role assigned to it. + Connectors_config_properties_cases_webhook: + title: Connector request properties for Webhook - Case Management connector + required: + - createIncidentJson + - createIncidentResponseKey + - createIncidentUrl + - getIncidentResponseExternalTitleKey + - getIncidentUrl + - updateIncidentJson + - updateIncidentUrl + - viewIncidentUrl + description: Defines properties for connectors when type is `.cases-webhook`. + type: object + properties: + createCommentJson: + type: string + description: > + A JSON payload sent to the create comment URL to create a case + comment. You can use variables to add Kibana Cases data to the + payload. The required variable is `case.comment`. Due to Mustache + template variables (the text enclosed in triple braces, for example, + `{{{case.title}}}`), the JSON is not validated when you create the + connector. The JSON is validated once the Mustache variables have + been placed when the REST method runs. Manually ensure that the JSON + is valid, disregarding the Mustache variables, so the later + validation will pass. + example: '{"body": {{{case.comment}}}}' + createCommentMethod: + type: string + description: > + The REST API HTTP request method to create a case comment in the + third-party system. Valid values are `patch`, `post`, and `put`. + default: put + enum: + - patch + - post + - put + createCommentUrl: + type: string + description: > + The REST API URL to create a case comment by ID in the third-party + system. You can use a variable to add the external system ID to the + URL. If you are using the `xpack.actions.allowedHosts setting`, add + the hostname to the allowed hosts. + example: https://example.com/issue/{{{external.system.id}}}/comment + createIncidentJson: + type: string + description: > + A JSON payload sent to the create case URL to create a case. You can + use variables to add case data to the payload. Required variables + are `case.title` and `case.description`. Due to Mustache template + variables (which is the text enclosed in triple braces, for example, + `{{{case.title}}}`), the JSON is not validated when you create the + connector. The JSON is validated after the Mustache variables have + been placed when REST method runs. Manually ensure that the JSON is + valid to avoid future validation errors; disregard Mustache + variables during your review. + example: >- + {"fields": {"summary": {{{case.title}}},"description": + {{{case.description}}},"labels": {{{case.tags}}}}} + createIncidentMethod: + type: string + description: > + The REST API HTTP request method to create a case in the third-party + system. Valid values are `patch`, `post`, and `put`. + enum: + - patch + - post + - put + default: post + createIncidentResponseKey: + type: string + description: >- + The JSON key in the create external case response that contains the + case ID. + createIncidentUrl: + type: string + description: > + The REST API URL to create a case in the third-party system. If you + are using the `xpack.actions.allowedHosts` setting, add the hostname + to the allowed hosts. + getIncidentResponseExternalTitleKey: + type: string + description: >- + The JSON key in get external case response that contains the case + title. + getIncidentUrl: + type: string + description: > + The REST API URL to get the case by ID from the third-party system. + If you are using the `xpack.actions.allowedHosts` setting, add the + hostname to the allowed hosts. You can use a variable to add the + external system ID to the URL. Due to Mustache template variables + (the text enclosed in triple braces, for example, + `{{{case.title}}}`), the JSON is not validated when you create the + connector. The JSON is validated after the Mustache variables have + been placed when REST method runs. Manually ensure that the JSON is + valid, disregarding the Mustache variables, so the later validation + will pass. + example: https://example.com/issue/{{{external.system.id}}} + hasAuth: + type: boolean + description: >- + If true, a username and password for login type authentication must + be provided. + default: true + headers: + type: string + description: > + A set of key-value pairs sent as headers with the request URLs for + the create case, update case, get case, and create comment methods. + updateIncidentJson: + type: string + description: > + The JSON payload sent to the update case URL to update the case. You + can use variables to add Kibana Cases data to the payload. Required + variables are `case.title` and `case.description`. Due to Mustache + template variables (which is the text enclosed in triple braces, for + example, `{{{case.title}}}`), the JSON is not validated when you + create the connector. The JSON is validated after the Mustache + variables have been placed when REST method runs. Manually ensure + that the JSON is valid to avoid future validation errors; disregard + Mustache variables during your review. + example: >- + {"fields": {"summary": {{{case.title}}},"description": + {{{case.description}}},"labels": {{{case.tags}}}}} + updateIncidentMethod: + type: string + description: > + The REST API HTTP request method to update the case in the + third-party system. Valid values are `patch`, `post`, and `put`. + default: put + enum: + - patch + - post + - put + updateIncidentUrl: + type: string + description: > + The REST API URL to update the case by ID in the third-party system. + You can use a variable to add the external system ID to the URL. If + you are using the `xpack.actions.allowedHosts` setting, add the + hostname to the allowed hosts. + example: https://example.com/issue/{{{external.system.ID}}} + viewIncidentUrl: + type: string + description: > + The URL to view the case in the external system. You can use + variables to add the external system ID or external system title to + the URL. + example: >- + https://testing-jira.atlassian.net/browse/{{{external.system.title}}} + Connectors_secrets_properties_cases_webhook: + title: Connector secrets properties for Webhook - Case Management connector + type: object + properties: + password: + type: string + description: >- + The password for HTTP basic authentication. If `hasAuth` is set to + `true`, this property is required. + user: + type: string + description: >- + The username for HTTP basic authentication. If `hasAuth` is set to + `true`, this property is required. + Connectors_config_properties_d3security: + title: Connector request properties for a D3 Security connector + description: Defines properties for connectors when type is `.d3security`. + type: object + required: + - url + properties: + url: + type: string + description: > + The D3 Security API request URL. If you are using the + `xpack.actions.allowedHosts` setting, add the hostname to the + allowed hosts. + Connectors_secrets_properties_d3security: + title: Connector secrets properties for a D3 Security connector + description: Defines secrets for connectors when type is `.d3security`. + required: + - token + type: object + properties: + token: + type: string + description: The D3 Security token. + Connectors_config_properties_email: + title: Connector request properties for an email connector + description: Defines properties for connectors when type is `.email`. + required: + - from + type: object + properties: + clientId: + description: > + The client identifier, which is a part of OAuth 2.0 client + credentials authentication, in GUID format. If `service` is + `exchange_server`, this property is required. + type: string + nullable: true + from: + description: > + The from address for all emails sent by the connector. It must be + specified in `user@host-name` format. + type: string + hasAuth: + description: > + Specifies whether a user and password are required inside the + secrets configuration. + default: true + type: boolean + host: + description: > + The host name of the service provider. If the `service` is + `elastic_cloud` (for Elastic Cloud notifications) or one of + Nodemailer's well-known email service providers, this property is + ignored. If `service` is `other`, this property must be defined. + type: string + oauthTokenUrl: + type: string + nullable: true + port: + description: > + The port to connect to on the service provider. If the `service` is + `elastic_cloud` (for Elastic Cloud notifications) or one of + Nodemailer's well-known email service providers, this property is + ignored. If `service` is `other`, this property must be defined. + type: integer + secure: + description: > + Specifies whether the connection to the service provider will use + TLS. If the `service` is `elastic_cloud` (for Elastic Cloud + notifications) or one of Nodemailer's well-known email service + providers, this property is ignored. + type: boolean + service: + description: | + The name of the email service. + type: string + enum: + - elastic_cloud + - exchange_server + - gmail + - other + - outlook365 + - ses + tenantId: + description: > + The tenant identifier, which is part of OAuth 2.0 client credentials + authentication, in GUID format. If `service` is `exchange_server`, + this property is required. + type: string + nullable: true + Connectors_secrets_properties_email: + title: Connector secrets properties for an email connector + description: Defines secrets for connectors when type is `.email`. + type: object + properties: + clientSecret: + type: string + description: > + The Microsoft Exchange Client secret for OAuth 2.0 client + credentials authentication. It must be URL-encoded. If `service` is + `exchange_server`, this property is required. + password: + type: string + description: > + The password for HTTP basic authentication. If `hasAuth` is set to + `true`, this property is required. + user: + type: string + description: > + The username for HTTP basic authentication. If `hasAuth` is set to + `true`, this property is required. + Connectors_config_properties_genai_azure: + title: >- + Connector request properties for an OpenAI connector that uses Azure + OpenAI + description: > + Defines properties for connectors when type is `.gen-ai` and the API + provider is `Azure OpenAI'. + type: object + required: + - apiProvider + - apiUrl + properties: + apiProvider: + type: string + description: The OpenAI API provider. + enum: + - Azure OpenAI + apiUrl: + type: string + description: The OpenAI API endpoint. + Connectors_config_properties_genai_openai: + title: Connector request properties for an OpenAI connector + description: > + Defines properties for connectors when type is `.gen-ai` and the API + provider is `OpenAI'. + type: object + required: + - apiProvider + - apiUrl + properties: + apiProvider: + type: string + description: The OpenAI API provider. + enum: + - OpenAI + apiUrl: + type: string + description: The OpenAI API endpoint. + defaultModel: + type: string + description: The default model to use for requests. + Connectors_config_properties_genai: + title: Connector request properties for an OpenAI connector + description: Defines properties for connectors when type is `.gen-ai`. + oneOf: + - $ref: '#/components/schemas/Connectors_config_properties_genai_azure' + - $ref: '#/components/schemas/Connectors_config_properties_genai_openai' + discriminator: + propertyName: apiProvider + mapping: + Azure OpenAI: '#/components/schemas/Connectors_config_properties_genai_azure' + OpenAI: '#/components/schemas/Connectors_config_properties_genai_openai' + Connectors_secrets_properties_genai: + title: Connector secrets properties for an OpenAI connector + description: Defines secrets for connectors when type is `.gen-ai`. + type: object + properties: + apiKey: + type: string + description: The OpenAI API key. + Connectors_config_properties_index: + title: Connector request properties for an index connector + required: + - index + description: Defines properties for connectors when type is `.index`. + type: object + properties: + executionTimeField: + description: A field that indicates when the document was indexed. + default: null + type: string + nullable: true + index: + description: The Elasticsearch index to be written to. + type: string + refresh: + description: > + The refresh policy for the write request, which affects when changes + are made visible to search. Refer to the refresh setting for + Elasticsearch document APIs. + default: false + type: boolean + Connectors_config_properties_jira: + title: Connector request properties for a Jira connector + required: + - apiUrl + - projectKey + description: Defines properties for connectors when type is `.jira`. + type: object + properties: + apiUrl: + description: The Jira instance URL. + type: string + projectKey: + description: The Jira project key. + type: string + Connectors_secrets_properties_jira: + title: Connector secrets properties for a Jira connector + required: + - apiToken + - email + description: Defines secrets for connectors when type is `.jira`. + type: object + properties: + apiToken: + description: The Jira API authentication token for HTTP basic authentication. + type: string + email: + description: The account email for HTTP Basic authentication. + type: string + Connectors_config_properties_opsgenie: + title: Connector request properties for an Opsgenie connector + required: + - apiUrl + description: Defines properties for connectors when type is `.opsgenie`. + type: object + properties: + apiUrl: + description: > + The Opsgenie URL. For example, `https://api.opsgenie.com` or + `https://api.eu.opsgenie.com`. If you are using the + `xpack.actions.allowedHosts` setting, add the hostname to the + allowed hosts. + type: string + Connectors_secrets_properties_opsgenie: + title: Connector secrets properties for an Opsgenie connector + required: + - apiKey + description: Defines secrets for connectors when type is `.opsgenie`. + type: object + properties: + apiKey: + description: The Opsgenie API authentication key for HTTP Basic authentication. + type: string + Connectors_config_properties_pagerduty: + title: Connector request properties for a PagerDuty connector + description: Defines properties for connectors when type is `.pagerduty`. + type: object + properties: + apiUrl: + description: The PagerDuty event URL. + type: string + nullable: true + example: https://events.pagerduty.com/v2/enqueue + Connectors_secrets_properties_pagerduty: + title: Connector secrets properties for a PagerDuty connector + description: Defines secrets for connectors when type is `.pagerduty`. + type: object + required: + - routingKey + properties: + routingKey: + description: > + A 32 character PagerDuty Integration Key for an integration on a + service. + type: string + Connectors_config_properties_resilient: + title: Connector request properties for a IBM Resilient connector + required: + - apiUrl + - orgId + description: Defines properties for connectors when type is `.resilient`. + type: object + properties: + apiUrl: + description: The IBM Resilient instance URL. + type: string + orgId: + description: The IBM Resilient organization ID. + type: string + Connectors_secrets_properties_resilient: + title: Connector secrets properties for IBM Resilient connector + required: + - apiKeyId + - apiKeySecret + description: Defines secrets for connectors when type is `.resilient`. + type: object + properties: + apiKeyId: + type: string + description: The authentication key ID for HTTP Basic authentication. + apiKeySecret: + type: string + description: The authentication key secret for HTTP Basic authentication. + Connectors_config_properties_sentinelone: + title: Connector request properties for a SentinelOne connector + required: + - url + description: Defines properties for connectors when type is `.sentinelone`. + type: object + properties: + url: + description: > + The SentinelOne tenant URL. If you are using the + `xpack.actions.allowedHosts` setting, add the hostname to the + allowed hosts. + type: string + Connectors_secrets_properties_sentinelone: + title: Connector secrets properties for a SentinelOne connector + description: Defines secrets for connectors when type is `.sentinelone`. + type: object + required: + - token + properties: + token: + description: The A SentinelOne API token. + type: string + Connectors_config_properties_servicenow: + title: Connector request properties for a ServiceNow ITSM connector + required: + - apiUrl + description: Defines properties for connectors when type is `.servicenow`. + type: object + properties: + apiUrl: + type: string + description: The ServiceNow instance URL. + clientId: + description: > + The client ID assigned to your OAuth application. This property is + required when `isOAuth` is `true`. + type: string + isOAuth: + description: > + The type of authentication to use. The default value is false, which + means basic authentication is used instead of open authorization + (OAuth). + default: false + type: boolean + jwtKeyId: + description: > + The key identifier assigned to the JWT verifier map of your OAuth + application. This property is required when `isOAuth` is `true`. + type: string + userIdentifierValue: + description: > + The identifier to use for OAuth authentication. This identifier + should be the user field you selected when you created an OAuth JWT + API endpoint for external clients in your ServiceNow instance. For + example, if the selected user field is `Email`, the user identifier + should be the user's email address. This property is required when + `isOAuth` is `true`. + type: string + usesTableApi: + description: > + Determines whether the connector uses the Table API or the Import + Set API. This property is supported only for ServiceNow ITSM and + ServiceNow SecOps connectors. NOTE: If this property is set to + `false`, the Elastic application should be installed in ServiceNow. + default: true + type: boolean + Connectors_secrets_properties_servicenow: + title: >- + Connector secrets properties for ServiceNow ITOM, ServiceNow ITSM, and + ServiceNow SecOps connectors + description: >- + Defines secrets for connectors when type is `.servicenow`, + `.servicenow-sir`, or `.servicenow-itom`. + type: object + properties: + clientSecret: + type: string + description: >- + The client secret assigned to your OAuth application. This property + is required when `isOAuth` is `true`. + password: + type: string + description: >- + The password for HTTP basic authentication. This property is + required when `isOAuth` is `false`. + privateKey: + type: string + description: >- + The RSA private key that you created for use in ServiceNow. This + property is required when `isOAuth` is `true`. + privateKeyPassword: + type: string + description: >- + The password for the RSA private key. This property is required when + `isOAuth` is `true` and you set a password on your private key. + username: + type: string + description: >- + The username for HTTP basic authentication. This property is + required when `isOAuth` is `false`. + Connectors_config_properties_servicenow_itom: + title: Connector request properties for a ServiceNow ITSM connector + required: + - apiUrl + description: Defines properties for connectors when type is `.servicenow`. + type: object + properties: + apiUrl: + type: string + description: The ServiceNow instance URL. + clientId: + description: > + The client ID assigned to your OAuth application. This property is + required when `isOAuth` is `true`. + type: string + isOAuth: + description: > + The type of authentication to use. The default value is false, which + means basic authentication is used instead of open authorization + (OAuth). + default: false + type: boolean + jwtKeyId: + description: > + The key identifier assigned to the JWT verifier map of your OAuth + application. This property is required when `isOAuth` is `true`. + type: string + userIdentifierValue: + description: > + The identifier to use for OAuth authentication. This identifier + should be the user field you selected when you created an OAuth JWT + API endpoint for external clients in your ServiceNow instance. For + example, if the selected user field is `Email`, the user identifier + should be the user's email address. This property is required when + `isOAuth` is `true`. + type: string + Connectors_config_properties_slack_api: + title: Connector request properties for a Slack connector + description: Defines properties for connectors when type is `.slack_api`. + type: object + properties: + allowedChannels: + type: array + description: A list of valid Slack channels. + items: + type: object + required: + - id + - name + maxItems: 25 + properties: + id: + type: string + description: The Slack channel ID. + example: C123ABC456 + minLength: 1 + name: + type: string + description: The Slack channel name. + minLength: 1 + Connectors_secrets_properties_slack_api: + title: Connector secrets properties for a Web API Slack connector + description: Defines secrets for connectors when type is `.slack`. + required: + - token + type: object + properties: + token: + type: string + description: Slack bot user OAuth token. + Connectors_secrets_properties_slack_webhook: + title: Connector secrets properties for a Webhook Slack connector + description: Defines secrets for connectors when type is `.slack`. + required: + - webhookUrl + type: object + properties: + webhookUrl: + type: string + description: Slack webhook url. + Connectors_config_properties_swimlane: + title: Connector request properties for a Swimlane connector + required: + - apiUrl + - appId + - connectorType + description: Defines properties for connectors when type is `.swimlane`. + type: object + properties: + apiUrl: + description: The Swimlane instance URL. + type: string + appId: + description: The Swimlane application ID. + type: string + connectorType: + description: >- + The type of connector. Valid values are `all`, `alerts`, and + `cases`. + type: string + enum: + - all + - alerts + - cases + mappings: + title: Connector mappings properties for a Swimlane connector + description: The field mapping. + type: object + properties: + alertIdConfig: + title: Alert identifier mapping + description: Mapping for the alert ID. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + caseIdConfig: + title: Case identifier mapping + description: Mapping for the case ID. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + caseNameConfig: + title: Case name mapping + description: Mapping for the case name. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + commentsConfig: + title: Case comment mapping + description: Mapping for the case comments. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + descriptionConfig: + title: Case description mapping + description: Mapping for the case description. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + ruleNameConfig: + title: Rule name mapping + description: Mapping for the name of the alert's rule. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + severityConfig: + title: Severity mapping + description: Mapping for the severity. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + Connectors_secrets_properties_swimlane: + title: Connector secrets properties for a Swimlane connector + description: Defines secrets for connectors when type is `.swimlane`. + type: object + properties: + apiToken: + description: Swimlane API authentication token. + type: string + Connectors_secrets_properties_teams: + title: Connector secrets properties for a Microsoft Teams connector + description: Defines secrets for connectors when type is `.teams`. + type: object + required: + - webhookUrl + properties: + webhookUrl: + type: string + description: > + The URL of the incoming webhook. If you are using the + `xpack.actions.allowedHosts` setting, add the hostname to the + allowed hosts. + Connectors_config_properties_tines: + title: Connector request properties for a Tines connector + description: Defines properties for connectors when type is `.tines`. + type: object + required: + - url + properties: + url: + description: > + The Tines tenant URL. If you are using the + `xpack.actions.allowedHosts` setting, make sure this hostname is + added to the allowed hosts. + type: string + Connectors_secrets_properties_tines: + title: Connector secrets properties for a Tines connector + description: Defines secrets for connectors when type is `.tines`. + type: object + required: + - email + - token + properties: + email: + description: The email used to sign in to Tines. + type: string + token: + description: The Tines API token. + type: string + Connectors_config_properties_torq: + title: Connector request properties for a Torq connector + description: Defines properties for connectors when type is `.torq`. + type: object + required: + - webhookIntegrationUrl + properties: + webhookIntegrationUrl: + description: The endpoint URL of the Elastic Security integration in Torq. + type: string + Connectors_secrets_properties_torq: + title: Connector secrets properties for a Torq connector + description: Defines secrets for connectors when type is `.torq`. + type: object + required: + - token + properties: + token: + description: The secret of the webhook authentication header. + type: string + Connectors_config_properties_webhook: + title: Connector request properties for a Webhook connector + description: Defines properties for connectors when type is `.webhook`. + type: object + properties: + authType: + type: string + nullable: true + enum: + - webhook-authentication-basic + - webhook-authentication-ssl + description: | + The type of authentication to use: basic, SSL, or none. + ca: + type: string + description: > + A base64 encoded version of the certificate authority file that the + connector can trust to sign and validate certificates. This option + is available for all authentication types. + certType: + type: string + description: > + If the `authType` is `webhook-authentication-ssl`, specifies whether + the certificate authentication data is in a CRT and key file format + or a PFX file format. + enum: + - ssl-crt-key + - ssl-pfx + hasAuth: + type: boolean + description: > + If `true`, a user name and password must be provided for login type + authentication. + headers: + type: object + nullable: true + description: A set of key-value pairs sent as headers with the request. + method: + type: string + default: post + enum: + - post + - put + description: | + The HTTP request method, either `post` or `put`. + url: + type: string + description: > + The request URL. If you are using the `xpack.actions.allowedHosts` + setting, add the hostname to the allowed hosts. + verificationMode: + type: string + enum: + - certificate + - full + - none + default: full + description: > + Controls the verification of certificates. Use `full` to validate + that the certificate has an issue date within the `not_before` and + `not_after` dates, chains to a trusted certificate authority (CA), + and has a hostname or IP address that matches the names within the + certificate. Use `certificate` to validate the certificate and + verify that it is signed by a trusted authority; this option does + not check the certificate hostname. Use `none` to skip certificate + validation. + Connectors_secrets_properties_webhook: + title: Connector secrets properties for a Webhook connector + description: Defines secrets for connectors when type is `.webhook`. + type: object + properties: + crt: + type: string + description: >- + If `authType` is `webhook-authentication-ssl` and `certType` is + `ssl-crt-key`, it is a base64 encoded version of the CRT or CERT + file. + key: + type: string + description: >- + If `authType` is `webhook-authentication-ssl` and `certType` is + `ssl-crt-key`, it is a base64 encoded version of the KEY file. + pfx: + type: string + description: >- + If `authType` is `webhook-authentication-ssl` and `certType` is + `ssl-pfx`, it is a base64 encoded version of the PFX or P12 file. + password: + type: string + description: > + The password for HTTP basic authentication or the passphrase for the + SSL certificate files. If `hasAuth` is set to `true` and `authType` + is `webhook-authentication-basic`, this property is required. + user: + type: string + description: > + The username for HTTP basic authentication. If `hasAuth` is set to + `true` and `authType` is `webhook-authentication-basic`, this + property is required. + Connectors_config_properties_xmatters: + title: Connector request properties for an xMatters connector + description: Defines properties for connectors when type is `.xmatters`. + type: object + properties: + configUrl: + description: > + The request URL for the Elastic Alerts trigger in xMatters. It is + applicable only when `usesBasic` is `true`. + type: string + nullable: true + usesBasic: + description: >- + Specifies whether the connector uses HTTP basic authentication + (`true`) or URL authentication (`false`). + type: boolean + default: true + Connectors_secrets_properties_xmatters: + title: Connector secrets properties for an xMatters connector + description: Defines secrets for connectors when type is `.xmatters`. + type: object + properties: + password: + description: > + A user name for HTTP basic authentication. It is applicable only + when `usesBasic` is `true`. + type: string + secretsUrl: + description: > + The request URL for the Elastic Alerts trigger in xMatters with the + API key included in the URL. It is applicable only when `usesBasic` + is `false`. + type: string + user: + description: > + A password for HTTP basic authentication. It is applicable only when + `usesBasic` is `true`. + type: string + Connectors_create_connector_request: + title: Create connector request body properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/Connectors_create_connector_request_bedrock' + - $ref: '#/components/schemas/Connectors_create_connector_request_gemini' + - $ref: >- + #/components/schemas/Connectors_create_connector_request_cases_webhook + - $ref: '#/components/schemas/Connectors_create_connector_request_d3security' + - $ref: '#/components/schemas/Connectors_create_connector_request_email' + - $ref: '#/components/schemas/Connectors_create_connector_request_genai' + - $ref: '#/components/schemas/Connectors_create_connector_request_index' + - $ref: '#/components/schemas/Connectors_create_connector_request_jira' + - $ref: '#/components/schemas/Connectors_create_connector_request_opsgenie' + - $ref: '#/components/schemas/Connectors_create_connector_request_pagerduty' + - $ref: '#/components/schemas/Connectors_create_connector_request_resilient' + - $ref: '#/components/schemas/Connectors_create_connector_request_sentinelone' + - $ref: '#/components/schemas/Connectors_create_connector_request_serverlog' + - $ref: '#/components/schemas/Connectors_create_connector_request_servicenow' + - $ref: >- + #/components/schemas/Connectors_create_connector_request_servicenow_itom + - $ref: >- + #/components/schemas/Connectors_create_connector_request_servicenow_sir + - $ref: '#/components/schemas/Connectors_create_connector_request_slack_api' + - $ref: >- + #/components/schemas/Connectors_create_connector_request_slack_webhook + - $ref: '#/components/schemas/Connectors_create_connector_request_swimlane' + - $ref: '#/components/schemas/Connectors_create_connector_request_teams' + - $ref: '#/components/schemas/Connectors_create_connector_request_tines' + - $ref: '#/components/schemas/Connectors_create_connector_request_torq' + - $ref: '#/components/schemas/Connectors_create_connector_request_webhook' + - $ref: '#/components/schemas/Connectors_create_connector_request_xmatters' + discriminator: + propertyName: connector_type_id + mapping: + .bedrock: '#/components/schemas/Connectors_create_connector_request_bedrock' + .gemini: '#/components/schemas/Connectors_create_connector_request_gemini' + .cases-webhook: >- + #/components/schemas/Connectors_create_connector_request_cases_webhook + .d3security: '#/components/schemas/Connectors_create_connector_request_d3security' + .email: '#/components/schemas/Connectors_create_connector_request_email' + .gen-ai: '#/components/schemas/Connectors_create_connector_request_genai' + .index: '#/components/schemas/Connectors_create_connector_request_index' + .jira: '#/components/schemas/Connectors_create_connector_request_jira' + .opsgenie: '#/components/schemas/Connectors_create_connector_request_opsgenie' + .pagerduty: '#/components/schemas/Connectors_create_connector_request_pagerduty' + .resilient: '#/components/schemas/Connectors_create_connector_request_resilient' + .sentinelone: '#/components/schemas/Connectors_create_connector_request_sentinelone' + .server-log: '#/components/schemas/Connectors_create_connector_request_serverlog' + .servicenow: '#/components/schemas/Connectors_create_connector_request_servicenow' + .servicenow-itom: >- + #/components/schemas/Connectors_create_connector_request_servicenow_itom + .servicenow-sir: >- + #/components/schemas/Connectors_create_connector_request_servicenow_sir + .slack_api: '#/components/schemas/Connectors_create_connector_request_slack_api' + .slack: >- + #/components/schemas/Connectors_create_connector_request_slack_webhook + .swimlane: '#/components/schemas/Connectors_create_connector_request_swimlane' + .teams: '#/components/schemas/Connectors_create_connector_request_teams' + .tines: '#/components/schemas/Connectors_create_connector_request_tines' + .torq: '#/components/schemas/Connectors_create_connector_request_torq' + .webhook: '#/components/schemas/Connectors_create_connector_request_webhook' + .xmatters: '#/components/schemas/Connectors_create_connector_request_xmatters' + Connectors_connector_response_properties_bedrock: + title: Connector response properties for an Amazon Bedrock connector + type: object + required: + - config + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_bedrock' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + Connectors_connector_response_properties_gemini: + title: Connector response properties for a Google Gemini connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_gemini' + connector_type_id: + type: string + description: The type of connector. + enum: + - .gemini + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_cases_webhook: + title: Connector request properties for a Webhook - Case Management connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_cases_webhook' + connector_type_id: + description: The type of connector. + type: string + enum: + - .cases-webhook + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_d3security: + title: Connector response properties for a D3 Security connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_d3security' + connector_type_id: + type: string + description: The type of connector. + enum: + - .d3security + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_email: + title: Connector response properties for an email connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_email' + connector_type_id: + type: string + description: The type of connector. + enum: + - .email + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_genai: + title: Connector response properties for an OpenAI connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_genai' + connector_type_id: + type: string + description: The type of connector. + enum: + - .gen-ai + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_index: + title: Connector response properties for an index connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_index' + connector_type_id: + type: string + description: The type of connector. + enum: + - .index + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_jira: + title: Connector response properties for a Jira connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_jira' + connector_type_id: + type: string + description: The type of connector. + enum: + - .jira + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_opsgenie: + title: Connector response properties for an Opsgenie connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_opsgenie' + connector_type_id: + type: string + description: The type of connector. + enum: + - .opsgenie + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_pagerduty: + title: Connector response properties for a PagerDuty connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_pagerduty' + connector_type_id: + type: string + description: The type of connector. + enum: + - .pagerduty + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_resilient: + title: Connector response properties for a IBM Resilient connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_resilient' + connector_type_id: + type: string + description: The type of connector. + enum: + - .resilient + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_sentinelone: + title: Connector response properties for a SentinelOne connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_sentinelone' + connector_type_id: + type: string + description: The type of connector. + enum: + - .sentinelone + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_serverlog: + title: Connector response properties for a server log connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + type: object + nullable: true + connector_type_id: + type: string + description: The type of connector. + enum: + - .server-log + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_servicenow: + title: Connector response properties for a ServiceNow ITSM connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_servicenow_itom: + title: Connector response properties for a ServiceNow ITOM connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow_itom' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-itom + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_servicenow_sir: + title: Connector response properties for a ServiceNow SecOps connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-sir + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_slack_api: + title: Connector response properties for a Slack connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_slack_api' + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack_api + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_slack_webhook: + title: Connector response properties for a Slack connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_swimlane: + title: Connector response properties for a Swimlane connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_swimlane' + connector_type_id: + type: string + description: The type of connector. + enum: + - .swimlane + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_teams: + title: Connector response properties for a Microsoft Teams connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + type: object + connector_type_id: + type: string + description: The type of connector. + enum: + - .teams + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_tines: + title: Connector response properties for a Tines connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_tines' + connector_type_id: + type: string + description: The type of connector. + enum: + - .tines + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_torq: + title: Connector response properties for a Torq connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_torq' + connector_type_id: + type: string + description: The type of connector. + enum: + - .torq + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_webhook: + title: Connector response properties for a Webhook connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_webhook' + connector_type_id: + type: string + description: The type of connector. + enum: + - .webhook + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_connector_response_properties_xmatters: + title: Connector response properties for an xMatters connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_xmatters' + connector_type_id: + type: string + description: The type of connector. + enum: + - .xmatters + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/Connectors_is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/Connectors_is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/Connectors_is_preconfigured' + is_system_action: + $ref: '#/components/schemas/Connectors_is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/Connectors_referenced_by_count' + Connectors_is_deprecated: + type: boolean + description: Indicates whether the connector type is deprecated. + example: false + Connectors_is_missing_secrets: + type: boolean + description: >- + Indicates whether secrets are missing for the connector. Secrets + configuration properties vary depending on the connector type. + example: false + Connectors_is_preconfigured: + type: boolean + description: > + Indicates whether it is a preconfigured connector. If true, the `config` + and `is_missing_secrets` properties are omitted from the response. + example: false + Connectors_is_system_action: + type: boolean + description: Indicates whether the connector is used for system actions. + example: false + Connectors_referenced_by_count: + type: integer + description: > + Indicates the number of saved objects that reference the connector. If + `is_preconfigured` is true, this value is not calculated. This property + is returned only by the get all connectors API. + example: 2 + Connectors_connector_response_properties: + title: Connector response properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_bedrock + - $ref: '#/components/schemas/Connectors_connector_response_properties_gemini' + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_cases_webhook + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_d3security + - $ref: '#/components/schemas/Connectors_connector_response_properties_email' + - $ref: '#/components/schemas/Connectors_connector_response_properties_genai' + - $ref: '#/components/schemas/Connectors_connector_response_properties_index' + - $ref: '#/components/schemas/Connectors_connector_response_properties_jira' + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_opsgenie + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_pagerduty + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_resilient + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_sentinelone + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_serverlog + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_servicenow + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_servicenow_itom + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_servicenow_sir + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_slack_api + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_slack_webhook + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_swimlane + - $ref: '#/components/schemas/Connectors_connector_response_properties_teams' + - $ref: '#/components/schemas/Connectors_connector_response_properties_tines' + - $ref: '#/components/schemas/Connectors_connector_response_properties_torq' + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_webhook + - $ref: >- + #/components/schemas/Connectors_connector_response_properties_xmatters + discriminator: + propertyName: connector_type_id + mapping: + .bedrock: >- + #/components/schemas/Connectors_connector_response_properties_bedrock + .gemini: '#/components/schemas/Connectors_connector_response_properties_gemini' + .cases-webhook: >- + #/components/schemas/Connectors_connector_response_properties_cases_webhook + .d3security: >- + #/components/schemas/Connectors_connector_response_properties_d3security + .email: '#/components/schemas/Connectors_connector_response_properties_email' + .gen-ai: '#/components/schemas/Connectors_connector_response_properties_genai' + .index: '#/components/schemas/Connectors_connector_response_properties_index' + .jira: '#/components/schemas/Connectors_connector_response_properties_jira' + .opsgenie: >- + #/components/schemas/Connectors_connector_response_properties_opsgenie + .pagerduty: >- + #/components/schemas/Connectors_connector_response_properties_pagerduty + .resilient: >- + #/components/schemas/Connectors_connector_response_properties_resilient + .sentinelone: >- + #/components/schemas/Connectors_connector_response_properties_sentinelone + .server-log: >- + #/components/schemas/Connectors_connector_response_properties_serverlog + .servicenow: >- + #/components/schemas/Connectors_connector_response_properties_servicenow + .servicenow-itom: >- + #/components/schemas/Connectors_connector_response_properties_servicenow_itom + .servicenow-sir: >- + #/components/schemas/Connectors_connector_response_properties_servicenow_sir + .slack_api: >- + #/components/schemas/Connectors_connector_response_properties_slack_api + .slack: >- + #/components/schemas/Connectors_connector_response_properties_slack_webhook + .swimlane: >- + #/components/schemas/Connectors_connector_response_properties_swimlane + .teams: '#/components/schemas/Connectors_connector_response_properties_teams' + .tines: '#/components/schemas/Connectors_connector_response_properties_tines' + .torq: '#/components/schemas/Connectors_connector_response_properties_torq' + .webhook: >- + #/components/schemas/Connectors_connector_response_properties_webhook + .xmatters: >- + #/components/schemas/Connectors_connector_response_properties_xmatters + Connectors_update_connector_request_bedrock: + title: Update Amazon Bedrock connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_bedrock' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_bedrock' + Connectors_update_connector_request_gemini: + title: Update Google Gemini connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_gemini' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_gemini' + Connectors_update_connector_request_cases_webhook: + title: Update Webhook - Case Managment connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_cases_webhook' + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_cases_webhook' + Connectors_update_connector_request_d3security: + title: Update D3 Security connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_d3security' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_d3security' + Connectors_update_connector_request_email: + title: Update email connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_email' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_email' + Connectors_update_connector_request_index: + title: Update index connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_index' + name: + type: string + description: The display name for the connector. + Connectors_update_connector_request_jira: + title: Update Jira connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_jira' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_jira' + Connectors_update_connector_request_opsgenie: + title: Update Opsgenie connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_opsgenie' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_opsgenie' + Connectors_update_connector_request_pagerduty: + title: Update PagerDuty connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_pagerduty' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_pagerduty' + Connectors_update_connector_request_resilient: + title: Update IBM Resilient connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_resilient' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_resilient' + Connectors_update_connector_request_sentinelone: + title: Update SentinelOne connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_sentinelone' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_sentinelone' + Connectors_update_connector_request_serverlog: + title: Update server log connector request + type: object + required: + - name + properties: + name: + type: string + description: The display name for the connector. + Connectors_update_connector_request_servicenow: + title: Update ServiceNow ITSM connector or ServiceNow SecOps request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_servicenow' + Connectors_update_connector_request_servicenow_itom: + title: Create ServiceNow ITOM connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_servicenow_itom' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_servicenow' + Connectors_update_connector_request_slack_api: + title: Update Slack connector request + type: object + required: + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_slack_api' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_slack_api' + Connectors_update_connector_request_slack_webhook: + title: Update Slack connector request + type: object + required: + - name + - secrets + properties: + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_slack_webhook' + Connectors_update_connector_request_swimlane: + title: Update Swimlane connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_swimlane' + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_swimlane' + Connectors_update_connector_request_teams: + title: Update Microsoft Teams connector request + type: object + required: + - name + - secrets + properties: + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_teams' + Connectors_update_connector_request_tines: + title: Update Tines connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_tines' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_tines' + Connectors_update_connector_request_torq: + title: Update Torq connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_torq' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_torq' + Connectors_update_connector_request_webhook: + title: Update Webhook connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_webhook' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_webhook' + Connectors_update_connector_request_xmatters: + title: Update xMatters connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/Connectors_config_properties_xmatters' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/Connectors_secrets_properties_xmatters' + Connectors_update_connector_request: + title: Update connector request body properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/Connectors_update_connector_request_bedrock' + - $ref: '#/components/schemas/Connectors_update_connector_request_gemini' + - $ref: >- + #/components/schemas/Connectors_update_connector_request_cases_webhook + - $ref: '#/components/schemas/Connectors_update_connector_request_d3security' + - $ref: '#/components/schemas/Connectors_update_connector_request_email' + - $ref: '#/components/schemas/Connectors_create_connector_request_genai' + - $ref: '#/components/schemas/Connectors_update_connector_request_index' + - $ref: '#/components/schemas/Connectors_update_connector_request_jira' + - $ref: '#/components/schemas/Connectors_update_connector_request_opsgenie' + - $ref: '#/components/schemas/Connectors_update_connector_request_pagerduty' + - $ref: '#/components/schemas/Connectors_update_connector_request_resilient' + - $ref: '#/components/schemas/Connectors_update_connector_request_sentinelone' + - $ref: '#/components/schemas/Connectors_update_connector_request_serverlog' + - $ref: '#/components/schemas/Connectors_update_connector_request_servicenow' + - $ref: >- + #/components/schemas/Connectors_update_connector_request_servicenow_itom + - $ref: '#/components/schemas/Connectors_update_connector_request_slack_api' + - $ref: >- + #/components/schemas/Connectors_update_connector_request_slack_webhook + - $ref: '#/components/schemas/Connectors_update_connector_request_swimlane' + - $ref: '#/components/schemas/Connectors_update_connector_request_teams' + - $ref: '#/components/schemas/Connectors_update_connector_request_tines' + - $ref: '#/components/schemas/Connectors_update_connector_request_torq' + - $ref: '#/components/schemas/Connectors_update_connector_request_webhook' + - $ref: '#/components/schemas/Connectors_update_connector_request_xmatters' + Connectors_features: + type: string + description: | + The feature that uses the connector. + enum: + - alerting + - cases + - generativeAIForSecurity + - generativeAIForObservability + - generativeAIForSearchPlayground + - siem + - uptime + Connectors_connector_types: + title: Connector types + type: string + description: >- + The type of connector. For example, `.email`, `.index`, `.jira`, + `.opsgenie`, or `.server-log`. + enum: + - .bedrock + - .gemini + - .cases-webhook + - .d3security + - .email + - .gen-ai + - .index + - .jira + - .opsgenie + - .pagerduty + - .resilient + - .sentinelone + - .servicenow + - .servicenow-itom + - .servicenow-sir + - .server-log + - .slack + - .slack_api + - .swimlane + - .teams + - .tines + - .torq + - .webhook + - .xmatters + example: .server-log + Data_views_400_response: + title: Bad request + type: object + required: + - statusCode + - error + - message + properties: + statusCode: + type: number + example: 400 + error: + type: string + example: Bad Request + message: + type: string + Data_views_allownoindex: + type: boolean + description: Allows the data view saved object to exist before the data is available. + Data_views_fieldattrs: + type: object + description: A map of field attributes by field name. + Data_views_fieldformats: + type: object + description: A map of field formats by field name. + Data_views_namespaces: + type: array + description: >- + An array of space identifiers for sharing the data view between multiple + spaces. + items: + type: string + default: default + Data_views_runtimefieldmap: + type: object + description: A map of runtime field definitions by field name. + Data_views_sourcefilters: + type: array + description: The array of field names you want to filter out in Discover. + items: + type: object + required: + - value + properties: + value: + type: string + Data_views_timefieldname: + type: string + description: The timestamp field name, which you use for time-based data views. + Data_views_title: + type: string + description: >- + Comma-separated list of data streams, indices, and aliases that you want + to search. Supports wildcards (`*`). + Data_views_type: + type: string + description: When set to `rollup`, identifies the rollup data views. + Data_views_typemeta: + type: object + description: >- + When you use rollup indices, contains the field list for the rollup data + view API endpoints. + Data_views_create_data_view_request_object: + title: Create data view request + type: object + required: + - data_view + properties: + data_view: + type: object + required: + - title + description: The data view object. + properties: + allowNoIndex: + $ref: '#/components/schemas/Data_views_allownoindex' + fieldAttrs: + $ref: '#/components/schemas/Data_views_fieldattrs' + fieldFormats: + $ref: '#/components/schemas/Data_views_fieldformats' + fields: + type: object + id: + type: string + name: + type: string + description: The data view name. + namespaces: + $ref: '#/components/schemas/Data_views_namespaces' + runtimeFieldMap: + $ref: '#/components/schemas/Data_views_runtimefieldmap' + sourceFilters: + $ref: '#/components/schemas/Data_views_sourcefilters' + timeFieldName: + $ref: '#/components/schemas/Data_views_timefieldname' + title: + $ref: '#/components/schemas/Data_views_title' + type: + $ref: '#/components/schemas/Data_views_type' + typeMeta: + $ref: '#/components/schemas/Data_views_typemeta' + version: + type: string + override: + type: boolean + description: >- + Override an existing data view if a data view with the provided + title already exists. + default: false + Data_views_data_view_response_object: + title: Data view response properties + type: object + properties: + data_view: + type: object + properties: + allowNoIndex: + $ref: '#/components/schemas/Data_views_allownoindex' + fieldAttrs: + $ref: '#/components/schemas/Data_views_fieldattrs' + fieldFormats: + $ref: '#/components/schemas/Data_views_fieldformats' + fields: + type: object + id: + type: string + example: ff959d40-b880-11e8-a6d9-e546fe2bba5f + name: + type: string + description: The data view name. + namespaces: + $ref: '#/components/schemas/Data_views_namespaces' + runtimeFieldMap: + $ref: '#/components/schemas/Data_views_runtimefieldmap' + sourceFilters: + $ref: '#/components/schemas/Data_views_sourcefilters' + timeFieldName: + $ref: '#/components/schemas/Data_views_timefieldname' + title: + $ref: '#/components/schemas/Data_views_title' + typeMeta: + $ref: '#/components/schemas/Data_views_typemeta' + version: + type: string + example: WzQ2LDJd + Data_views_404_response: + type: object + properties: + error: + type: string + example: Not Found + enum: + - Not Found + message: + type: string + example: >- + Saved object [index-pattern/caaad6d0-920c-11ed-b36a-874bd1548a00] + not found + statusCode: + type: integer + example: 404 + enum: + - 404 + Data_views_update_data_view_request_object: + title: Update data view request + type: object + required: + - data_view + properties: + data_view: + type: object + description: > + The data view properties you want to update. Only the specified + properties are updated in the data view. Unspecified fields stay as + they are persisted. + properties: + allowNoIndex: + $ref: '#/components/schemas/Data_views_allownoindex' + fieldFormats: + $ref: '#/components/schemas/Data_views_fieldformats' + fields: + type: object + name: + type: string + runtimeFieldMap: + $ref: '#/components/schemas/Data_views_runtimefieldmap' + sourceFilters: + $ref: '#/components/schemas/Data_views_sourcefilters' + timeFieldName: + $ref: '#/components/schemas/Data_views_timefieldname' + title: + $ref: '#/components/schemas/Data_views_title' + type: + $ref: '#/components/schemas/Data_views_type' + typeMeta: + $ref: '#/components/schemas/Data_views_typemeta' + refresh_fields: + type: boolean + description: Reloads the data view fields after the data view is updated. + default: false + Machine_learning_APIs_mlSyncResponseSuccess: + type: boolean + description: The success or failure of the synchronization. + Machine_learning_APIs_mlSyncResponseAnomalyDetectors: + type: object + title: Sync API response for anomaly detection jobs + description: >- + The sync machine learning saved objects API response contains this + object when there are anomaly detection jobs affected by the + synchronization. There is an object for each relevant job, which + contains the synchronization status. + properties: + success: + $ref: '#/components/schemas/Machine_learning_APIs_mlSyncResponseSuccess' + Machine_learning_APIs_mlSyncResponseDatafeeds: + type: object + title: Sync API response for datafeeds + description: >- + The sync machine learning saved objects API response contains this + object when there are datafeeds affected by the synchronization. There + is an object for each relevant datafeed, which contains the + synchronization status. + properties: + success: + $ref: '#/components/schemas/Machine_learning_APIs_mlSyncResponseSuccess' + Machine_learning_APIs_mlSyncResponseDataFrameAnalytics: + type: object + title: Sync API response for data frame analytics jobs + description: >- + The sync machine learning saved objects API response contains this + object when there are data frame analytics jobs affected by the + synchronization. There is an object for each relevant job, which + contains the synchronization status. + properties: + success: + $ref: '#/components/schemas/Machine_learning_APIs_mlSyncResponseSuccess' + Machine_learning_APIs_mlSyncResponseSavedObjectsCreated: + type: object + title: Sync API response for created saved objects + description: >- + If saved objects are missing for machine learning jobs or trained + models, they are created when you run the sync machine learning saved + objects API. + properties: + anomaly-detector: + type: object + description: >- + If saved objects are missing for anomaly detection jobs, they are + created. + additionalProperties: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseAnomalyDetectors + data-frame-analytics: + type: object + description: >- + If saved objects are missing for data frame analytics jobs, they are + created. + additionalProperties: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseDataFrameAnalytics + trained-model: + type: object + description: If saved objects are missing for trained models, they are created. + additionalProperties: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseTrainedModels + Machine_learning_APIs_mlSyncResponseSavedObjectsDeleted: + type: object + title: Sync API response for deleted saved objects + description: >- + If saved objects exist for machine learning jobs or trained models that + no longer exist, they are deleted when you run the sync machine learning + saved objects API. + properties: + anomaly-detector: + type: object + description: >- + If there are saved objects exist for nonexistent anomaly detection + jobs, they are deleted. + additionalProperties: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseAnomalyDetectors + data-frame-analytics: + type: object + description: >- + If there are saved objects exist for nonexistent data frame + analytics jobs, they are deleted. + additionalProperties: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseDataFrameAnalytics + trained-model: + type: object + description: >- + If there are saved objects exist for nonexistent trained models, + they are deleted. + additionalProperties: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseTrainedModels + Machine_learning_APIs_mlSyncResponseTrainedModels: + type: object + title: Sync API response for trained models + description: >- + The sync machine learning saved objects API response contains this + object when there are trained models affected by the synchronization. + There is an object for each relevant trained model, which contains the + synchronization status. + properties: + success: + $ref: '#/components/schemas/Machine_learning_APIs_mlSyncResponseSuccess' + Machine_learning_APIs_mlSync200Response: + type: object + title: Successful sync API response + properties: + datafeedsAdded: + type: object + description: >- + If a saved object for an anomaly detection job is missing a datafeed + identifier, it is added when you run the sync machine learning saved + objects API. + additionalProperties: + $ref: '#/components/schemas/Machine_learning_APIs_mlSyncResponseDatafeeds' + datafeedsRemoved: + type: object + description: >- + If a saved object for an anomaly detection job references a datafeed + that no longer exists, it is deleted when you run the sync machine + learning saved objects API. + additionalProperties: + $ref: '#/components/schemas/Machine_learning_APIs_mlSyncResponseDatafeeds' + savedObjectsCreated: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseSavedObjectsCreated + savedObjectsDeleted: + $ref: >- + #/components/schemas/Machine_learning_APIs_mlSyncResponseSavedObjectsDeleted + Machine_learning_APIs_mlSync4xxResponse: + type: object + title: Unsuccessful sync API response + properties: + error: + type: string + example: Unauthorized + message: + type: string + statusCode: + type: integer + example: 401 + Serverless_saved_objects_400_response: + title: Bad request + type: object + required: + - error + - message + - statusCode + properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 + Serverless_saved_objects_export_objects_request: + type: object + properties: + excludeExportDetails: + description: Do not add export details entry at the end of the stream. + type: boolean + default: false + includeReferencesDeep: + description: Includes all of the referenced objects in the exported objects. + type: boolean + objects: + description: A list of objects to export. + type: array + items: + type: object + type: + description: >- + The saved object types to include in the export. Use `*` to export + all the types. + oneOf: + - type: string + - type: array + items: + type: string + Serverless_saved_objects_import_objects_request: + type: object + properties: + file: + description: > + A file exported using the export API. NOTE: The + `savedObjects.maxImportExportSize` configuration setting limits the + number of saved objects which may be included in this file. + Similarly, the `savedObjects.maxImportPayloadBytes` setting limits + the overall size of the file that can be imported. + Serverless_saved_objects_200_import_objects_response: + type: object + properties: + success: + type: boolean + description: > + Indicates when the import was successfully completed. When set to + false, some objects may not have been created. For additional + information, refer to the `errors` and `successResults` properties. + successCount: + type: integer + description: Indicates the number of successfully imported records. + errors: + type: array + items: + type: object + description: > + Indicates the import was unsuccessful and specifies the objects that + failed to import. + + + NOTE: One object may result in multiple errors, which requires + separate steps to resolve. For instance, a `missing_references` + error and conflict error. + successResults: + type: array + items: + type: object + description: > + Indicates the objects that are successfully imported, with any + metadata if applicable. + + + NOTE: Objects are created only when all resolvable errors are + addressed, including conflicts and missing references. If objects + are created as new copies, each entry in the `successResults` array + includes a `destinationId` attribute. + examples: + Connectors_create_email_connector_request: + summary: Create an email connector. + value: + name: email-connector-1 + connector_type_id: .email + config: + from: tester@example.com + hasAuth: true + host: https://example.com + port: 1025 + secure: false + service: other + secrets: + user: username + password: password + Connectors_create_index_connector_request: + summary: Create an index connector. + value: + name: my-connector + connector_type_id: .index + config: + index: test-index + Connectors_create_webhook_connector_request: + summary: Create a webhook connector with SSL authentication. + value: + name: my-webhook-connector + connector_type_id: .webhook + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + secrets: + crt: QmFnIEF0dH... + key: LS0tLS1CRUdJ... + password: my-passphrase + Connectors_create_xmatters_connector_request: + summary: Create an xMatters connector with URL authentication. + value: + name: my-xmatters-connector + connector_type_id: .xmatters + config: + usesBasic: false + secrets: + secretsUrl: https://example.com?apiKey=xxxxx + Connectors_create_email_connector_response: + summary: A new email connector. + value: + id: 90a82c60-478f-11ee-a343-f98a117c727f + connector_type_id: .email + name: email-connector-1 + config: + from: tester@example.com + service: other + host: https://example.com + port: 1025 + secure: false + hasAuth: true + tenantId: null + clientId: null + oauthTokenUrl: null + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + Connectors_create_index_connector_response: + summary: A new index connector. + value: + id: c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad + connector_type_id: .index + name: my-connector + config: + index: test-index + refresh: false + executionTimeField: null + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + Connectors_create_webhook_connector_response: + summary: A new webhook connector. + value: + id: 900eb010-3b9d-11ee-a642-8ffbb94e38bd + name: my-webhook-connector + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + verificationMode: full + headers: null + hasAuth: true + connector_type_id: .webhook + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + Connectors_create_xmatters_connector_response: + summary: A new xMatters connector. + value: + id: 4d2d8da0-4d1f-11ee-9367-577408be4681 + name: my-xmatters-connector + config: + usesBasic: false + configUrl: null + connector_type_id: .xmatters + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + Connectors_get_connector_response: + summary: Get connector details. + value: + id: df770e30-8b8b-11ed-a780-3b746c987a81 + name: my_server_log_connector + config: {} + connector_type_id: .server-log + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + Connectors_update_index_connector_request: + summary: Update an index connector. + value: + name: updated-connector + config: + index: updated-index + Connectors_get_connectors_response: + summary: A list of connectors + value: + - id: preconfigured-email-connector + name: my-preconfigured-email-notification + connector_type_id: .email + is_preconfigured: true + is_deprecated: false + referenced_by_count: 0 + is_system_action: false + - id: e07d0c80-8b8b-11ed-a780-3b746c987a81 + name: my-index-connector + config: + index: test-index + refresh: false + executionTimeField: null + connector_type_id: .index + is_preconfigured: false + is_deprecated: false + referenced_by_count: 2 + is_missing_secrets: false + is_system_action: false + Connectors_get_connector_types_generativeai_response: + summary: A list of connector types for the `generativeAI` feature. + value: + - id: .gen-ai + name: OpenAI + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAIForSecurity + - generativeAIForObservability + - generativeAIForSearchPlayground + is_system_action_type: false + - id: .bedrock + name: AWS Bedrock + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAIForSecurity + - generativeAIForObservability + - generativeAIForSearchPlayground + is_system_action_type: false + - id: .gemini + name: Google Gemini + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAIForSecurity + is_system_action_type: false + Data_views_get_data_views_response: + summary: The get all data views API returns a list of data views. + value: + data_view: + - id: ff959d40-b880-11e8-a6d9-e546fe2bba5f + namespaces: + - default + title: kibana_sample_data_ecommerce + typeMeta: {} + name: Kibana Sample Data eCommerce + - id: d3d7af60-4c81-11e8-b3d7-01146121b73d + namespaces: + - default + title: kibana_sample_data_flights + name: Kibana Sample Data Flights + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + namespaces: + - default + title: kibana_sample_data_logs + name: Kibana Sample Data Logs + Data_views_create_data_view_request: + summary: Create a data view with runtime fields. + value: + data_view: + title: logstash-* + name: My Logstash data view + runtimeFieldMap: + runtime_shape_name: + type: keyword + script: + source: emit(doc['shape_name'].value) + Data_views_get_data_view_response: + summary: >- + The get data view API returns a JSON object that contains information + about the data view. + value: + data_view: + id: ff959d40-b880-11e8-a6d9-e546fe2bba5f + version: WzUsMV0= + title: kibana_sample_data_ecommerce + timeFieldName: order_date + sourceFilters: [] + fields: + _id: + count: 0 + name: _id + type: string + esTypes: + - _id + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + _index: + count: 0 + name: _index + type: string + esTypes: + - _index + scripted: false + searchable: true + aggregatable: true + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + _score: + count: 0 + name: _score + type: number + scripted: false + searchable: false + aggregatable: false + readFromDocValues: false + format: + id: number + shortDotsEnable: false + isMapped: true + _source: + count: 0 + name: _source + type: _source + esTypes: + - _source + scripted: false + searchable: false + aggregatable: false + readFromDocValues: false + format: + id: _source + shortDotsEnable: false + isMapped: true + category: + count: 0 + name: category + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + category.keyword: + count: 0 + name: category.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: category + format: + id: string + shortDotsEnable: false + isMapped: true + currency: + count: 0 + name: currency + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + customer_birth_date: + count: 0 + name: customer_birth_date + type: date + esTypes: + - date + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: date + shortDotsEnable: false + isMapped: true + customer_first_name: + count: 0 + name: customer_first_name + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + customer_first_name.keyword: + count: 0 + name: customer_first_name.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: customer_first_name + format: + id: string + shortDotsEnable: false + isMapped: true + customer_full_name: + count: 0 + name: customer_full_name + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + customer_full_name.keyword: + count: 0 + name: customer_full_name.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: customer_full_name + format: + id: string + shortDotsEnable: false + isMapped: true + customer_gender: + count: 0 + name: customer_gender + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + customer_id: + count: 0 + name: customer_id + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + customer_last_name: + count: 0 + name: customer_last_name + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + customer_last_name.keyword: + count: 0 + name: customer_last_name.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: customer_last_name + format: + id: string + shortDotsEnable: false + isMapped: true + customer_phone: + count: 0 + name: customer_phone + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + day_of_week: + count: 0 + name: day_of_week + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + day_of_week_i: + count: 0 + name: day_of_week_i + type: number + esTypes: + - integer + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + email: + count: 0 + name: email + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + event.dataset: + count: 0 + name: event.dataset + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + geoip.city_name: + count: 0 + name: geoip.city_name + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + geoip.continent_name: + count: 0 + name: geoip.continent_name + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + geoip.country_iso_code: + count: 0 + name: geoip.country_iso_code + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + geoip.location: + count: 0 + name: geoip.location + type: geo_point + esTypes: + - geo_point + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: geo_point + params: + transform: wkt + shortDotsEnable: false + isMapped: true + geoip.region_name: + count: 0 + name: geoip.region_name + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + manufacturer: + count: 0 + name: manufacturer + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + manufacturer.keyword: + count: 0 + name: manufacturer.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: manufacturer + format: + id: string + shortDotsEnable: false + isMapped: true + order_date: + count: 0 + name: order_date + type: date + esTypes: + - date + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: date + shortDotsEnable: false + isMapped: true + order_id: + count: 0 + name: order_id + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + products._id: + count: 0 + name: products._id + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + products._id.keyword: + count: 0 + name: products._id.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: products._id + format: + id: string + shortDotsEnable: false + isMapped: true + products.base_price: + count: 0 + name: products.base_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + products.base_unit_price: + count: 0 + name: products.base_unit_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + products.category: + count: 0 + name: products.category + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + products.category.keyword: + count: 0 + name: products.category.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: products.category + format: + id: string + shortDotsEnable: false + isMapped: true + products.created_on: + count: 0 + name: products.created_on + type: date + esTypes: + - date + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: date + shortDotsEnable: false + isMapped: true + products.discount_amount: + count: 0 + name: products.discount_amount + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + products.discount_percentage: + count: 0 + name: products.discount_percentage + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + products.manufacturer: + count: 1 + name: products.manufacturer + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + products.manufacturer.keyword: + count: 0 + name: products.manufacturer.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: products.manufacturer + format: + id: string + shortDotsEnable: false + isMapped: true + products.min_price: + count: 0 + name: products.min_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + products.price: + count: 1 + name: products.price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + products.product_id: + count: 0 + name: products.product_id + type: number + esTypes: + - long + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + products.product_name: + count: 1 + name: products.product_name + type: string + esTypes: + - text + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + products.product_name.keyword: + count: 0 + name: products.product_name.keyword + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + subType: + multi: + parent: products.product_name + format: + id: string + shortDotsEnable: false + isMapped: true + products.quantity: + count: 0 + name: products.quantity + type: number + esTypes: + - integer + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + products.sku: + count: 0 + name: products.sku + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + products.tax_amount: + count: 0 + name: products.tax_amount + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + products.taxful_price: + count: 0 + name: products.taxful_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + products.taxless_price: + count: 0 + name: products.taxless_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + products.unit_discount_amount: + count: 0 + name: products.unit_discount_amount + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + sku: + count: 0 + name: sku + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + taxful_total_price: + count: 0 + name: taxful_total_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.[00] + shortDotsEnable: false + isMapped: true + taxless_total_price: + count: 0 + name: taxless_total_price + type: number + esTypes: + - half_float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.00 + shortDotsEnable: false + isMapped: true + total_quantity: + count: 1 + name: total_quantity + type: number + esTypes: + - integer + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + total_unique_products: + count: 0 + name: total_unique_products + type: number + esTypes: + - integer + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + type: + count: 0 + name: type + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + user: + count: 0 + name: user + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + typeMeta: {} + fieldFormats: + taxful_total_price: + id: number + params: + pattern: $0,0.[00] + products.price: + id: number + params: + pattern: $0,0.00 + taxless_total_price: + id: number + params: + pattern: $0,0.00 + products.taxless_price: + id: number + params: + pattern: $0,0.00 + products.taxful_price: + id: number + params: + pattern: $0,0.00 + products.min_price: + id: number + params: + pattern: $0,0.00 + products.base_unit_price: + id: number + params: + pattern: $0,0.00 + products.base_price: + id: number + params: + pattern: $0,0.00 + runtimeFieldMap: {} + fieldAttrs: + products.manufacturer: + count: 1 + products.price: + count: 1 + products.product_name: + count: 1 + total_quantity: + count: 1 + allowNoIndex: false + name: Kibana Sample Data eCommerce + namespaces: + - default + Data_views_update_data_view_request: + summary: Update some properties for a data view. + value: + data_view: + title: kibana_sample_data_ecommerce + timeFieldName: order_date + allowNoIndex: false + name: Kibana Sample Data eCommerce + refresh_fields: true + Data_views_get_default_data_view_response: + summary: The get default data view API returns the default data view identifier. + value: + data_view_id: ff959d40-b880-11e8-a6d9-e546fe2bba5f + Data_views_set_default_data_view_request: + summary: Set the default data view identifier. + value: + data_view_id: ff959d40-b880-11e8-a6d9-e546fe2bba5f + force: true + Data_views_update_field_metadata_request: + summary: Set popularity count for field foo. + value: + fields: + foo: + count: 123 + Data_views_create_runtime_field_request: + summary: Create a runtime field. + value: + name: runtimeFoo + runtimeField: + type: long + script: + source: emit(doc["foo"].value) + Data_views_get_runtime_field_response: + summary: >- + The get runtime field API returns a JSON object that contains + information about the runtime field (`hour_of_day`) and the data view + (`d3d7af60-4c81-11e8-b3d7-01146121b73d`). + value: + fields: + - count: 0 + name: hour_of_day + type: number + esTypes: + - long + scripted: false + searchable: true + aggregatable: true + readFromDocValues: false + shortDotsEnable: false + runtimeField: + type: long + script: + source: emit(doc['timestamp'].value.getHour()); + data_view: + id: d3d7af60-4c81-11e8-b3d7-01146121b73d + version: WzM2LDJd + title: kibana_sample_data_flights + timeFieldName: timestamp + sourceFilters: [] + fields: + hour_of_day: + count: 0 + name: hour_of_day + type: number + esTypes: + - long + scripted: false + searchable: true + aggregatable: true + readFromDocValues: false + format: + id: number + params: + pattern: '00' + shortDotsEnable: false + runtimeField: + type: long + script: + source: emit(doc['timestamp'].value.getHour()); + AvgTicketPrice: + count: 0 + name: AvgTicketPrice + type: number + esTypes: + - float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + params: + pattern: $0,0.[00] + shortDotsEnable: false + isMapped: true + Cancelled: + count: 0 + name: Cancelled + type: boolean + esTypes: + - boolean + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: boolean + shortDotsEnable: false + isMapped: true + Carrier: + count: 0 + name: Carrier + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + Dest: + count: 0 + name: Dest + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + DestAirportID: + count: 0 + name: DestAirportID + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + DestCityName: + count: 0 + name: DestCityName + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + DestCountry: + count: 0 + name: DestCountry + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + DestLocation: + count: 0 + name: DestLocation + type: geo_point + esTypes: + - geo_point + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: geo_point + params: + transform: wkt + shortDotsEnable: false + isMapped: true + DestRegion: + count: 0 + name: DestRegion + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + DestWeather: + count: 0 + name: DestWeather + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + DistanceKilometers: + count: 0 + name: DistanceKilometers + type: number + esTypes: + - float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + DistanceMiles: + count: 0 + name: DistanceMiles + type: number + esTypes: + - float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + FlightDelay: + count: 0 + name: FlightDelay + type: boolean + esTypes: + - boolean + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: boolean + shortDotsEnable: false + isMapped: true + FlightDelayMin: + count: 0 + name: FlightDelayMin + type: number + esTypes: + - integer + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + FlightDelayType: + count: 0 + name: FlightDelayType + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + FlightNum: + count: 0 + name: FlightNum + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + FlightTimeHour: + count: 0 + name: FlightTimeHour + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + FlightTimeMin: + count: 0 + name: FlightTimeMin + type: number + esTypes: + - float + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + Origin: + count: 0 + name: Origin + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + OriginAirportID: + count: 0 + name: OriginAirportID + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + OriginCityName: + count: 0 + name: OriginCityName + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + OriginCountry: + count: 0 + name: OriginCountry + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + OriginLocation: + count: 0 + name: OriginLocation + type: geo_point + esTypes: + - geo_point + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: geo_point + params: + transform: wkt + shortDotsEnable: false + isMapped: true + OriginRegion: + count: 0 + name: OriginRegion + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + OriginWeather: + count: 0 + name: OriginWeather + type: string + esTypes: + - keyword + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: string + shortDotsEnable: false + isMapped: true + _id: + count: 0 + name: _id + type: string + esTypes: + - _id + scripted: false + searchable: true + aggregatable: false + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + _index: + count: 0 + name: _index + type: string + esTypes: + - _index + scripted: false + searchable: true + aggregatable: true + readFromDocValues: false + format: + id: string + shortDotsEnable: false + isMapped: true + _score: + count: 0 + name: _score + type: number + scripted: false + searchable: false + aggregatable: false + readFromDocValues: false + format: + id: number + shortDotsEnable: false + isMapped: true + _source: + count: 0 + name: _source + type: _source + esTypes: + - _source + scripted: false + searchable: false + aggregatable: false + readFromDocValues: false + format: + id: _source + shortDotsEnable: false + isMapped: true + dayOfWeek: + count: 0 + name: dayOfWeek + type: number + esTypes: + - integer + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: number + shortDotsEnable: false + isMapped: true + timestamp: + count: 0 + name: timestamp + type: date + esTypes: + - date + scripted: false + searchable: true + aggregatable: true + readFromDocValues: true + format: + id: date + shortDotsEnable: false + isMapped: true + fieldFormats: + hour_of_day: + id: number + params: + pattern: '00' + AvgTicketPrice: + id: number + params: + pattern: $0,0.[00] + runtimeFieldMap: + hour_of_day: + type: long + script: + source: emit(doc['timestamp'].value.getHour()); + fieldAttrs: {} + allowNoIndex: false + name: Kibana Sample Data Flights + Data_views_update_runtime_field_request: + summary: Update an existing runtime field on a data view. + value: + runtimeField: + script: + source: emit(doc["bar"].value) + Machine_learning_APIs_mlSyncExample: + summary: Two anomaly detection jobs required synchronization in this example. + value: + savedObjectsCreated: + anomaly-detector: + myjob1: + success: true + myjob2: + success: true + savedObjectsDeleted: {} + datafeedsAdded: {} + datafeedsRemoved: {} + Serverless_saved_objects_export_objects_request: + summary: Export a specific saved object. + value: + objects: + - type: map + id: de71f4f0-1902-11e9-919b-ffe5949a18d2 + includeReferencesDeep: false + excludeExportDetails: true + Serverless_saved_objects_export_objects_response: + summary: >- + The export objects API response contains a JSON record for each exported + object. + value: + attributes: + description: '' + layerListJSON: >- + [{"id":"0hmz5","alpha":1,"sourceDescriptor":{"type":"EMS_TMS","isAutoSelect":true,"lightModeDefault":"road_map_desaturated"},"visible":true,"style":{},"type":"EMS_VECTOR_TILE","minZoom":0,"maxZoom":24},{"id":"edh66","label":"Total + Requests by + Destination","minZoom":0,"maxZoom":24,"alpha":0.5,"sourceDescriptor":{"type":"EMS_FILE","id":"world_countries","tooltipProperties":["name","iso2"]},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"__kbnjoin__count__673ff994-fc75-4c67-909b-69fcb0e1060e","origin":"join"},"color":"Greys","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"GEOJSON_VECTOR","joins":[{"leftField":"iso2","right":{"type":"ES_TERM_SOURCE","id":"673ff994-fc75-4c67-909b-69fcb0e1060e","indexPatternTitle":"kibana_sample_data_logs","term":"geo.dest","indexPatternRefName":"layer_1_join_0_index_pattern","metrics":[{"type":"count","label":"web + logs + count"}],"applyGlobalQuery":true}}]},{"id":"gaxya","label":"Actual + Requests","minZoom":9,"maxZoom":24,"alpha":1,"sourceDescriptor":{"id":"b7486535-171b-4d3b-bb2e-33c1a0a2854c","type":"ES_SEARCH","geoField":"geo.coordinates","limit":2048,"filterByMapBounds":true,"tooltipProperties":["clientip","timestamp","host","request","response","machine.os","agent","bytes"],"indexPatternRefName":"layer_2_source_index_pattern","applyGlobalQuery":true,"scalingType":"LIMIT"},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"STATIC","options":{"color":"#2200ff"}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":2}},"iconSize":{"type":"DYNAMIC","options":{"field":{"name":"bytes","origin":"source"},"minSize":1,"maxSize":23,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"GEOJSON_VECTOR"},{"id":"tfi3f","label":"Total + Requests and + Bytes","minZoom":0,"maxZoom":9,"alpha":1,"sourceDescriptor":{"type":"ES_GEO_GRID","resolution":"COARSE","id":"8aaa65b5-a4e9-448b-9560-c98cb1c5ac5b","geoField":"geo.coordinates","requestType":"point","metrics":[{"type":"count","label":"web + logs + count"},{"type":"sum","field":"bytes"}],"indexPatternRefName":"layer_3_source_index_pattern","applyGlobalQuery":true},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"color":"Blues","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#cccccc"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"DYNAMIC","options":{"field":{"name":"sum_of_bytes","origin":"source"},"minSize":7,"maxSize":25,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelText":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelSize":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"minSize":12,"maxSize":24,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"GEOJSON_VECTOR"}] + mapStateJSON: >- + {"zoom":3.64,"center":{"lon":-88.92107,"lat":42.16337},"timeFilters":{"from":"now-7d","to":"now"},"refreshConfig":{"isPaused":true,"interval":0},"query":{"language":"kuery","query":""},"settings":{"autoFitToDataBounds":false}} + title: '[Logs] Total Requests and Bytes' + uiStateJSON: '{"isDarkMode":false}' + coreMigrationVersion: 8.8.0 + created_at: '2023-08-23T20:03:32.204Z' + id: de71f4f0-1902-11e9-919b-ffe5949a18d2 + managed: false + references: + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + name: layer_1_join_0_index_pattern + type: index-pattern + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + name: layer_2_source_index_pattern + type: index-pattern + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + name: layer_3_source_index_pattern + type: index-pattern + type: map + typeMigrationVersion: 8.4.0 + updated_at: '2023-08-23T20:03:32.204Z' + version: WzEzLDFd + Serverless_saved_objects_import_objects_request: + value: + file: file.ndjson + Serverless_saved_objects_import_objects_response: + summary: >- + The import objects API response indicates a successful import and the + objects are created. Since these objects are created as new copies, each + entry in the successResults array includes a destinationId attribute. + value: + successCount: 1 + success: true + successResults: + - type: index-pattern + id: 90943e30-9a47-11e8-b64d-95841ca0b247 + meta: + title: Kibana Sample Data Logs + icon: indexPatternApp + managed: false + destinationId: 82d2760c-468f-49cf-83aa-b9a35b6a8943 + responses: + Connectors_401: + description: Authorization information is missing or invalid. + content: + application/json: + schema: + type: object + title: Unauthorized response + properties: + error: + type: string + example: Unauthorized + enum: + - Unauthorized + message: + type: string + statusCode: + type: integer + example: 401 + enum: + - 401 + Connectors_404: + description: Object is not found. + content: + application/json: + schema: + type: object + title: Not found response + properties: + error: + type: string + example: Not Found + enum: + - Not Found + message: + type: string + example: >- + Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not + found + statusCode: + type: integer + example: 404 + enum: + - 404 +x-tagGroups: + - name: APM UI + tags: + - APM agent keys + - APM annotations + - name: Connectors + tags: + - connectors + - name: Data views + tags: + - data views + - name: Machine learning APIs + tags: + - ml + - name: Serverless saved objects + tags: + - saved objects diff --git a/oas_docs/makefile b/oas_docs/makefile new file mode 100644 index 0000000000000..805da0b6218a7 --- /dev/null +++ b/oas_docs/makefile @@ -0,0 +1,29 @@ +# ELASTICSEARCH CONFIDENTIAL +# __________________ +# +# Copyright Elasticsearch B.V. All rights reserved. +# +# NOTICE: All information contained herein is, and remains +# the property of Elasticsearch B.V. and its suppliers, if any. +# The intellectual and technical concepts contained herein +# are proprietary to Elasticsearch B.V. and its suppliers and +# may be covered by U.S. and Foreign Patents, patents in +# process, and are protected by trade secret or copyright +# law. Dissemination of this information or reproduction of +# this material is strictly forbidden unless prior written +# permission is obtained from Elasticsearch B.V. + +.PHONY: api-docs +api-docs: ## Generate kibana.serverless.yaml + @npx @redocly/cli join "kibana.info.serverless.yaml" "../x-pack/plugins/observability_solution/apm/docs/openapi/apm.yaml" "../x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml" "../src/plugins/data_views/docs/openapi/bundled.yaml" "../x-pack/plugins/ml/common/openapi/ml_apis_serverless.yaml" "../packages/core/saved-objects/docs/openapi/bundled_serverless.yaml" -o "kibana.serverless.yaml" --prefix-components-with-info-prop title + +.PHONY: api-docs-lint +api-docs-lint: ## Run spectral API docs linter + @npx @stoplight/spectral-cli lint "kibana.serverless.yaml" --ruleset ".spectral.yaml" + +help: ## Display help + @awk 'BEGIN {FS = ":.*##"; printf "Usage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) +#------------- -------------- + +.DEFAULT_GOAL := help + From 08561554ef7d5c5d18a7a8ef5d545d3bed8ac4db Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Wed, 19 Jun 2024 16:59:14 +0100 Subject: [PATCH 123/127] [Entity Analytics] Asset criticality bulk upload JSON API (#186310) ## Summary Add the asset criticality bulk upload API at `POST /api/asset_criticality/bulk`. Records supplied will either be created or updated. This API has the same functionality as the csv upload API but takes a JSON body. A couple slight differences: - only 1000 records can be supplied, I think this is a good number, I have capped this so we dont have to parse a huge body, I think if users want more than this in a single request they can use CSV which is better suited (parses request as data is received instead of parsing in one go) - Validation is done up front not line by line, if an invalid record is received the whole request is aborted with a 400, no records are changed or added. - Example curl (note asset criticality advanced setting must be enabled otherwise you will get a 403): ``` > curl -X POST $KIBANA_URL/api/asset_criticality/bulk \ --header "kbn-xsrf: true" \ --header "Content-Type: application/json" \ --header "elastic-api-version: 2023-10-31" \ --data '{ "records": [ { "id_field": "host.name", "id_value": "host-1", "criticality_level": "low_impact" }, { "id_field": "host.name", "id_value": "host-2", "criticality_level": "high_impact" } ] }' ``` I have added API tests for the new route --- .../bulk_upload_asset_criticality.gen.ts | 24 ++++ .../bulk_upload_asset_criticality.schema.yaml | 52 +++++++++ .../asset_criticality/common.gen.ts | 29 +++++ .../asset_criticality/common.schema.yaml | 53 ++++++++- .../create_asset_criticality.schema.yaml | 4 +- .../asset_criticality/index.ts | 2 +- .../upload_asset_criticality_csv.gen.ts | 36 ------ .../upload_asset_criticality_csv.schema.yaml | 47 +------- .../asset_criticality/constants.ts | 2 + .../public/entity_analytics/api/api.ts | 6 +- .../components/result_step.tsx | 4 +- .../reducer.test.ts | 4 +- .../reducer.ts | 6 +- .../asset_criticality_data_client.ts | 8 +- .../asset_criticality/routes/bulk_upload.ts | 106 ++++++++++++++++++ .../register_asset_criticality_routes.ts | 2 + .../asset_criticality/routes/upload_csv.ts | 4 +- .../asset_criticality/routes/upsert.ts | 8 +- .../lib/telemetry/event_based/events.ts | 8 +- .../asset_criticality.ts | 104 +++++++++++++++++ .../utils/asset_criticality.ts | 18 ++- 21 files changed, 418 insertions(+), 109 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts create mode 100644 x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml delete mode 100644 x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts new file mode 100644 index 0000000000000..c0d00e394b6b1 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Asset Criticality Bulk Upsert Schema + * version: 1 + */ + +import { z } from 'zod'; + +import { CreateAssetCriticalityRecord } from './common.gen'; + +export type AssetCriticalityBulkUploadRequest = z.infer; +export const AssetCriticalityBulkUploadRequest = z.object({ + records: z.array(CreateAssetCriticalityRecord).min(1).max(1000), +}); diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml new file mode 100644 index 0000000000000..b4b7d5d2f1fe4 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml @@ -0,0 +1,52 @@ +openapi: 3.0.0 +info: + version: '1' + title: Asset Criticality Bulk Upsert Schema +servers: + - url: 'http://{kibana_host}:{port}' + variables: + kibana_host: + default: localhost + port: + default: '5601' +paths: + /api/asset_criticality/bulk: + post: + x-labels: [ess, serverless] + summary: Bulk upsert asset criticality data, creating or updating records as needed + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AssetCriticalityBulkUploadRequest' + + responses: + '200': + description: Bulk upload successful + content: + application/json: + schema: + $ref: './common.schema.yaml#/components/schemas/AssetCriticalityBulkUploadResponse' + '413': + description: File too large +components: + schemas: + AssetCriticalityBulkUploadRequest: + type: object + example: + records: + - id_value: 'host-1' + id_field: 'host.name' + criticality_level: 'low_impact' + - id_value: 'host-2' + id_field: 'host.name' + criticality_level: 'medium_impact' + properties: + records: + type: array + minItems: 1 + maxItems: 1000 + items: + $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord' + required: + - records diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts index feff1e5126b78..4b689d22944e1 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts @@ -50,6 +50,14 @@ export type CreateAssetCriticalityRecord = z.infer; +export const CreateSingleAssetCriticalityRequest = CreateAssetCriticalityRecord.merge( + z.object({ /** * If 'wait_for' the request will wait for the index refresh. */ @@ -76,3 +84,24 @@ export const AssetCriticalityRecord = CreateAssetCriticalityRecord.merge( '@timestamp': z.string().datetime(), }) ); + +export type AssetCriticalityBulkUploadErrorItem = z.infer< + typeof AssetCriticalityBulkUploadErrorItem +>; +export const AssetCriticalityBulkUploadErrorItem = z.object({ + message: z.string(), + index: z.number().int(), +}); + +export type AssetCriticalityBulkUploadStats = z.infer; +export const AssetCriticalityBulkUploadStats = z.object({ + successful: z.number().int(), + failed: z.number().int(), + total: z.number().int(), +}); + +export type AssetCriticalityBulkUploadResponse = z.infer; +export const AssetCriticalityBulkUploadResponse = z.object({ + errors: z.array(AssetCriticalityBulkUploadErrorItem), + stats: AssetCriticalityBulkUploadStats, +}); diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml index 294cba2dd89ea..3218ec07e0fe2 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml @@ -49,7 +49,6 @@ components: - high_impact - extreme_impact description: The criticality level of the asset. - CreateAssetCriticalityRecord: allOf: - $ref: '#/components/schemas/AssetCriticalityRecordIdParts' @@ -57,12 +56,17 @@ components: properties: criticality_level: $ref: '#/components/schemas/AssetCriticalityLevel' + required: + - criticality_level + CreateSingleAssetCriticalityRequest: + allOf: + - $ref: '#/components/schemas/CreateAssetCriticalityRecord' + - type: object + properties: refresh: type: string enum: [wait_for] description: If 'wait_for' the request will wait for the index refresh. - required: - - criticality_level DeleteAssetCriticalityRecord: allOf: - $ref: '#/components/schemas/AssetCriticalityRecordIdParts' @@ -84,3 +88,46 @@ components: description: The time the record was created or updated. required: - '@timestamp' + AssetCriticalityBulkUploadErrorItem: + type: object + properties: + message: + type: string + index: + type: integer + required: + - message + - index + AssetCriticalityBulkUploadStats: + type: object + properties: + successful: + type: integer + failed: + type: integer + total: + type: integer + required: + - successful + - failed + - total + AssetCriticalityBulkUploadResponse: + type: object + example: + errors: + - message: 'Invalid ID field' + index: 0 + stats: + successful: 1 + failed: 1 + total: 2 + properties: + errors: + type: array + items: + $ref: '#/components/schemas/AssetCriticalityBulkUploadErrorItem' + stats: + $ref: '#/components/schemas/AssetCriticalityBulkUploadStats' + required: + - errors + - stats diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml index 4b5e52b5eb211..d59ce99c8717c 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml @@ -21,7 +21,7 @@ paths: content: application/json: schema: - $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord' + $ref: './common.schema.yaml#/components/schemas/CreateSingleAssetCriticalityRequest' responses: '200': description: Successful response @@ -41,7 +41,7 @@ paths: content: application/json: schema: - $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord' + $ref: './common.schema.yaml#/components/schemas/CreateSingleAssetCriticalityRequest' responses: '200': description: Successful response diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts index cc79a94a41fcb..5394f0c9cf69f 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts @@ -7,5 +7,5 @@ export * from './common.gen'; export * from './get_asset_criticality_status.gen'; -export * from './upload_asset_criticality_csv.gen'; export * from './get_asset_criticality_privileges.gen'; +export * from './bulk_upload_asset_criticality.gen'; diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts deleted file mode 100644 index dcad4f6596bac..0000000000000 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/* - * NOTICE: Do not edit this file manually. - * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. - * - * info: - * title: Asset Criticality Create Record Schema - * version: 1 - */ - -import { z } from 'zod'; - -export type ErrorItem = z.infer; -export const ErrorItem = z.object({ - message: z.string(), - index: z.number().int(), -}); - -export type Stats = z.infer; -export const Stats = z.object({ - successful: z.number().int(), - failed: z.number().int(), - total: z.number().int(), -}); - -export type AssetCriticalityCsvUploadResponse = z.infer; -export const AssetCriticalityCsvUploadResponse = z.object({ - errors: z.array(ErrorItem), - stats: Stats, -}); diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml index 933839cea43a3..c348dcefa8b78 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: version: '1' - title: Asset Criticality Create Record Schema + title: Asset Criticality CSV Upload Schema servers: - url: 'http://{kibana_host}:{port}' variables: @@ -29,11 +29,11 @@ paths: - file responses: '200': - description: CSV upload successful + description: Bulk upload successful content: application/json: schema: - $ref: '#/components/schemas/AssetCriticalityCsvUploadResponse' + $ref: '#./common/components/schemas/AssetCriticalityBulkUploadResponse' '413': description: File too large /api/asset_criticality/upload_csv: @@ -55,47 +55,10 @@ paths: - file responses: '200': - description: CSV upload successful + description: Bulk upload successful content: application/json: schema: - $ref: '#/components/schemas/AssetCriticalityCsvUploadResponse' + $ref: '#./common/components/schemas/AssetCriticalityBulkUploadResponse' '413': description: File too large -components: - schemas: - ErrorItem: - type: object - properties: - message: - type: string - index: - type: integer - required: - - message - - index - Stats: - type: object - properties: - successful: - type: integer - failed: - type: integer - total: - type: integer - required: - - successful - - failed - - total - AssetCriticalityCsvUploadResponse: - type: object - properties: - errors: - type: array - items: - $ref: '#/components/schemas/ErrorItem' - stats: - $ref: '#/components/schemas/Stats' - required: - - errors - - stats diff --git a/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts b/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts index d7d9854834d09..42be15209624c 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/asset_criticality/constants.ts @@ -16,6 +16,8 @@ export const ASSET_CRITICALITY_INTERNAL_CSV_UPLOAD_URL = export const ASSET_CRITICALITY_PUBLIC_URL = `/api/asset_criticality` as const; export const ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL = `${ASSET_CRITICALITY_PUBLIC_URL}/upload_csv` as const; +export const ASSET_CRITICALITY_PUBLIC_BULK_UPLOAD_URL = + `${ASSET_CRITICALITY_PUBLIC_URL}/bulk` as const; export const ASSET_CRITICALITY_INDEX_PATTERN = '.asset-criticality.asset-criticality-*'; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts index da391a9b30432..aa3b432533027 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts @@ -18,7 +18,7 @@ import type { RiskScoresEntityCalculationRequest, RiskScoresEntityCalculationResponse, } from '../../../common/api/entity_analytics/risk_engine/entity_calculation_route.gen'; -import type { AssetCriticalityCsvUploadResponse } from '../../../common/entity_analytics/asset_criticality/types'; +import type { AssetCriticalityBulkUploadResponse } from '../../../common/entity_analytics/asset_criticality/types'; import type { AssetCriticalityRecord, EntityAnalyticsPrivileges, @@ -181,12 +181,12 @@ export const useEntityAnalyticsRoutes = () => { const uploadAssetCriticalityFile = async ( fileContent: string, fileName: string - ): Promise => { + ): Promise => { const file = new File([new Blob([fileContent])], fileName, { type: 'text/csv' }); const body = new FormData(); body.append('file', file); - return http.fetch( + return http.fetch( ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL, { version: API_VERSIONS.public.v1, diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx index 30834f2fb8c32..1652c85eace1f 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx @@ -18,11 +18,11 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; -import type { AssetCriticalityCsvUploadResponse } from '../../../../../common/entity_analytics/asset_criticality/types'; +import type { AssetCriticalityBulkUploadResponse } from '../../../../../common/entity_analytics/asset_criticality/types'; import { buildAnnotationsFromError } from '../helpers'; export const AssetCriticalityResultStep: React.FC<{ - result?: AssetCriticalityCsvUploadResponse; + result?: AssetCriticalityBulkUploadResponse; validLinesAsText: string; errorMessage?: string; onReturn: () => void; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts index 68f7814d3113a..60b6191a777d6 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { AssetCriticalityCsvUploadResponse } from '../../../../common/api/entity_analytics'; +import type { AssetCriticalityBulkUploadResponse } from '../../../../common/api/entity_analytics'; import type { ReducerAction, ReducerState, ValidationStepState } from './reducer'; import { reducer } from './reducer'; import { FileUploaderSteps } from './types'; @@ -43,7 +43,7 @@ describe('reducer', () => { }); it('should handle "fileUploaded" action with response', () => { - const response: AssetCriticalityCsvUploadResponse = { + const response: AssetCriticalityBulkUploadResponse = { errors: [], stats: { total: 10, diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts index 0868caf2d624b..e7f233015434f 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { AssetCriticalityCsvUploadResponse } from '../../../../common/entity_analytics/asset_criticality/types'; +import type { AssetCriticalityBulkUploadResponse } from '../../../../common/entity_analytics/asset_criticality/types'; import { FileUploaderSteps } from './types'; import type { ValidatedFile } from './types'; import { isFilePickerStep, isValidationStep } from './helpers'; @@ -26,7 +26,7 @@ export interface ValidationStepState { export interface ResultStepState { step: FileUploaderSteps.RESULT; - fileUploadResponse?: AssetCriticalityCsvUploadResponse; + fileUploadResponse?: AssetCriticalityBulkUploadResponse; fileUploadError?: string; validLinesAsText: string; } @@ -46,7 +46,7 @@ export type ReducerAction = | { type: 'uploadingFile' } | { type: 'fileUploaded'; - payload: { response?: AssetCriticalityCsvUploadResponse; errorMessage?: string }; + payload: { response?: AssetCriticalityBulkUploadResponse; errorMessage?: string }; }; export const INITIAL_STATE: FilePickerState = { diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts index fd5c2921972f3..c5abf75b71478 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts @@ -10,7 +10,7 @@ import type { Logger, ElasticsearchClient } from '@kbn/core/server'; import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import type { AuditLogger } from '@kbn/security-plugin-types-server'; import type { - AssetCriticalityCsvUploadResponse, + AssetCriticalityBulkUploadResponse, AssetCriticalityUpsert, } from '../../../../common/entity_analytics/asset_criticality/types'; import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; @@ -183,9 +183,9 @@ export class AssetCriticalityDataClient { recordsStream, flushBytes, retries, - }: BulkUpsertFromStreamOptions): Promise => { - const errors: AssetCriticalityCsvUploadResponse['errors'] = []; - const stats: AssetCriticalityCsvUploadResponse['stats'] = { + }: BulkUpsertFromStreamOptions): Promise => { + const errors: AssetCriticalityBulkUploadResponse['errors'] = []; + const stats: AssetCriticalityBulkUploadResponse['stats'] = { successful: 0, failed: 0, total: 0, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts new file mode 100644 index 0000000000000..efc03a4adacd0 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { Logger } from '@kbn/core/server'; +import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils'; +import { transformError } from '@kbn/securitysolution-es-utils'; +import { Readable } from 'node:stream'; +import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import type { AssetCriticalityBulkUploadResponse } from '../../../../../common/api/entity_analytics'; +import { AssetCriticalityBulkUploadRequest } from '../../../../../common/api/entity_analytics'; +import type { ConfigType } from '../../../../config'; +import { + ASSET_CRITICALITY_PUBLIC_BULK_UPLOAD_URL, + APP_ID, + ENABLE_ASSET_CRITICALITY_SETTING, + API_VERSIONS, +} from '../../../../../common/constants'; +import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; +import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled'; +import type { EntityAnalyticsRoutesDeps } from '../../types'; +import { AssetCriticalityAuditActions } from '../audit'; +import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; + +export const assetCriticalityPublicBulkUploadRoute = ( + router: EntityAnalyticsRoutesDeps['router'], + logger: Logger, + config: ConfigType +) => { + router.versioned + .post({ + access: 'public', + path: ASSET_CRITICALITY_PUBLIC_BULK_UPLOAD_URL, + options: { + tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`], + }, + }) + .addVersion( + { + version: API_VERSIONS.public.v1, + validate: { + request: { + body: buildRouteValidationWithZod(AssetCriticalityBulkUploadRequest), + }, + }, + }, + async (context, request, response) => { + const { errorRetries, maxBulkRequestBodySizeBytes } = + config.entityAnalytics.assetCriticality.csvUpload; + const { records } = request.body; + + const securitySolution = await context.securitySolution; + securitySolution.getAuditLogger()?.log({ + message: 'User attempted to assign many asset criticalities via bulk upload', + event: { + action: AssetCriticalityAuditActions.ASSET_CRITICALITY_BULK_UPDATE, + category: AUDIT_CATEGORY.DATABASE, + type: AUDIT_TYPE.CREATION, + outcome: AUDIT_OUTCOME.UNKNOWN, + }, + }); + + const start = new Date(); + const siemResponse = buildSiemResponse(response); + + try { + await assertAdvancedSettingsEnabled(await context.core, ENABLE_ASSET_CRITICALITY_SETTING); + await checkAndInitAssetCriticalityResources(context, logger); + const assetCriticalityClient = securitySolution.getAssetCriticalityDataClient(); + + const formattedRecords = records.map((record) => ({ + idField: record.id_field, + idValue: record.id_value, + criticalityLevel: record.criticality_level, + })); + + const recordsStream = Readable.from(formattedRecords, { objectMode: true }); + + const { errors, stats } = await assetCriticalityClient.bulkUpsertFromStream({ + recordsStream, + retries: errorRetries, + flushBytes: maxBulkRequestBodySizeBytes, + }); + const end = new Date(); + + const tookMs = end.getTime() - start.getTime(); + logger.debug( + `Asset criticality Bulk upload completed in ${tookMs}ms ${JSON.stringify(stats)}` + ); + + const resBody: AssetCriticalityBulkUploadResponse = { errors, stats }; + + return response.ok({ body: resBody }); + } catch (e) { + logger.error(`Error during asset criticality bulk upload: ${e}`); + const error = transformError(e); + return siemResponse.error({ + statusCode: error.statusCode, + body: error.message, + }); + } + } + ); +}; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts index c211b1260b664..1f380de7df300 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/register_asset_criticality_routes.ts @@ -14,6 +14,7 @@ import { assetCriticalityPublicCSVUploadRoute, } from './upload_csv'; import type { EntityAnalyticsRoutesDeps } from '../../types'; +import { assetCriticalityPublicBulkUploadRoute } from './bulk_upload'; export const registerAssetCriticalityRoutes = ({ router, @@ -31,6 +32,7 @@ export const registerAssetCriticalityRoutes = ({ // Public routes assetCriticalityPublicCSVUploadRoute(router, logger, config, getStartServices); + assetCriticalityPublicBulkUploadRoute(router, logger, config); assetCriticalityPublicDeleteRoute(router, logger); assetCriticalityPublicGetRoute(router, logger); assetCriticalityPublicUpsertRoute(router, logger); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts index bd0a64fb08da7..9c9fa19ca3cbd 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts @@ -10,7 +10,7 @@ import { schema } from '@kbn/config-schema'; import Papa from 'papaparse'; import { transformError } from '@kbn/securitysolution-es-utils'; import type internal from 'stream'; -import type { AssetCriticalityCsvUploadResponse } from '../../../../../common/api/entity_analytics'; +import type { AssetCriticalityBulkUploadResponse } from '../../../../../common/api/entity_analytics'; import { CRITICALITY_CSV_MAX_SIZE_BYTES_WITH_TOLERANCE } from '../../../../../common/entity_analytics/asset_criticality'; import type { ConfigType } from '../../../../config'; import type { HapiReadableStream, SecuritySolutionRequestHandlerContext } from '../../../../types'; @@ -88,7 +88,7 @@ const handler: ( logger.debug(`Asset criticality CSV upload completed in ${tookMs}ms ${JSON.stringify(stats)}`); // type assignment here to ensure that the response body stays in sync with the API schema - const resBody: AssetCriticalityCsvUploadResponse = { errors, stats }; + const resBody: AssetCriticalityBulkUploadResponse = { errors, stats }; const [eventType, event] = createAssetCriticalityProcessedFileEvent({ startTime: start, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts index 78fbe29786298..cb3c36f450e43 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts @@ -17,7 +17,7 @@ import { API_VERSIONS, } from '../../../../../common/constants'; import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources'; -import { CreateAssetCriticalityRecord } from '../../../../../common/api/entity_analytics'; +import { CreateSingleAssetCriticalityRequest } from '../../../../../common/api/entity_analytics'; import type { EntityAnalyticsRoutesDeps } from '../../types'; import { AssetCriticalityAuditActions } from '../audit'; import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit'; @@ -26,7 +26,7 @@ import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setti type UpsertHandler = ( context: SecuritySolutionRequestHandlerContext, request: { - body: CreateAssetCriticalityRecord; + body: CreateSingleAssetCriticalityRequest; }, response: KibanaResponseFactory ) => Promise; @@ -93,7 +93,7 @@ export const assetCriticalityInternalUpsertRoute = ( version: API_VERSIONS.internal.v1, validate: { request: { - body: buildRouteValidationWithZod(CreateAssetCriticalityRecord), + body: buildRouteValidationWithZod(CreateSingleAssetCriticalityRequest), }, }, }, @@ -118,7 +118,7 @@ export const assetCriticalityPublicUpsertRoute = ( version: API_VERSIONS.public.v1, validate: { request: { - body: buildRouteValidationWithZod(CreateAssetCriticalityRecord), + body: buildRouteValidationWithZod(CreateSingleAssetCriticalityRequest), }, }, }, diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts b/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts index 03552f02e39cf..97a4d44fcd594 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts @@ -5,7 +5,7 @@ * 2.0. */ import type { EventTypeOpts } from '@kbn/core/server'; -import type { AssetCriticalityCsvUploadResponse } from '../../../../common/api/entity_analytics'; +import type { AssetCriticalityBulkUploadResponse } from '../../../../common/api/entity_analytics'; export const RISK_SCORE_EXECUTION_SUCCESS_EVENT: EventTypeOpts<{ scoresWritten: number; @@ -88,7 +88,7 @@ interface AssetCriticalitySystemProcessedAssignmentFileEvent { endTime: string; tookMs: number; }; - result?: AssetCriticalityCsvUploadResponse['stats']; + result?: AssetCriticalityBulkUploadResponse['stats']; status: 'success' | 'partial_success' | 'fail'; } @@ -124,7 +124,7 @@ export const ASSET_CRITICALITY_SYSTEM_PROCESSED_ASSIGNMENT_FILE_EVENT: EventType }; interface CreateAssetCriticalityProcessedFileEvent { - result?: AssetCriticalityCsvUploadResponse['stats']; + result?: AssetCriticalityBulkUploadResponse['stats']; startTime: Date; endTime: Date; } @@ -154,7 +154,7 @@ export const createAssetCriticalityProcessedFileEvent = ({ ]; }; -const getUploadStatus = (stats?: AssetCriticalityCsvUploadResponse['stats']) => { +const getUploadStatus = (stats?: AssetCriticalityBulkUploadResponse['stats']) => { if (!stats) { return 'fail'; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts index 7a7f50c5741ec..fa3f3e0e67f38 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/asset_criticality.ts @@ -6,6 +6,8 @@ */ import expect from '@kbn/expect'; +import { omit } from 'lodash'; +import { CreateAssetCriticalityRecord } from '@kbn/security-solution-plugin/common/api/entity_analytics'; import { cleanRiskEngine, cleanAssetCriticality, @@ -206,6 +208,108 @@ export default ({ getService }: FtrProviderContext) => { }); }); + describe('bulk upload', () => { + const expectAssetCriticalityDocMatching = async (expectedDoc: { + id_field: string; + id_value: string; + criticality_level: string; + }) => { + const esDoc = await getAssetCriticalityDoc({ + es, + idField: expectedDoc.id_field, + idValue: expectedDoc.id_value, + }); + + expect(omit(esDoc, '@timestamp')).to.eql(expectedDoc); + }; + + it('should return 400 if the records array is empty', async () => { + await assetCriticalityRoutes.bulkUpload([], { + expectStatusCode: 400, + }); + }); + + it('should return 400 if the records array is too large', async () => { + const records = new Array(1001).fill({ + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'high_impact', + }); + + await assetCriticalityRoutes.bulkUpload(records, { + expectStatusCode: 400, + }); + }); + + it('should return a 403 if the advanced setting is disabled', async () => { + await disableAssetCriticalityAdvancedSetting(kibanaServer, log); + + const validRecord: CreateAssetCriticalityRecord = { + id_field: 'host.name', + id_value: 'delete-me', + criticality_level: 'high_impact', + }; + + await assetCriticalityRoutes.bulkUpload([validRecord], { + expectStatusCode: 403, + }); + }); + + it('should correctly upload a valid record for one entity', async () => { + const validRecord: CreateAssetCriticalityRecord = { + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'high_impact', + }; + + const { body } = await assetCriticalityRoutes.bulkUpload([validRecord]); + expect(body.errors).to.eql([]); + expect(body.stats).to.eql({ + total: 1, + successful: 1, + failed: 0, + }); + + await expectAssetCriticalityDocMatching(validRecord); + }); + + it('should correctly upload valid records for multiple entities', async () => { + const validRecords: CreateAssetCriticalityRecord[] = Array.from({ length: 50 }, (_, i) => ({ + id_field: 'host.name', + id_value: `host-${i}`, + criticality_level: 'high_impact', + })); + + const { body } = await assetCriticalityRoutes.bulkUpload(validRecords); + expect(body.errors).to.eql([]); + expect(body.stats).to.eql({ + total: validRecords.length, + successful: validRecords.length, + failed: 0, + }); + + await Promise.all(validRecords.map(expectAssetCriticalityDocMatching)); + }); + + it('should return a 400 if a record is invalid', async () => { + const invalidRecord = { + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'invalid', + } as unknown as CreateAssetCriticalityRecord; + + const validRecord: CreateAssetCriticalityRecord = { + id_field: 'host.name', + id_value: 'host-2', + criticality_level: 'high_impact', + }; + + await assetCriticalityRoutes.bulkUpload([invalidRecord, validRecord], { + expectStatusCode: 400, + }); + }); + }); + describe('delete', () => { it('should correctly delete asset criticality', async () => { const assetCriticality = { diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts index da786269519db..ac7dfd170e412 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts @@ -17,8 +17,12 @@ import { ASSET_CRITICALITY_INTERNAL_PRIVILEGES_URL, ENABLE_ASSET_CRITICALITY_SETTING, API_VERSIONS, + ASSET_CRITICALITY_PUBLIC_BULK_UPLOAD_URL, } from '@kbn/security-solution-plugin/common/constants'; -import type { AssetCriticalityRecord } from '@kbn/security-solution-plugin/common/api/entity_analytics'; +import type { + AssetCriticalityRecord, + CreateAssetCriticalityRecord, +} from '@kbn/security-solution-plugin/common/api/entity_analytics'; import type { Client } from '@elastic/elasticsearch'; import type { ToolingLog } from '@kbn/tooling-log'; import querystring from 'querystring'; @@ -155,6 +159,18 @@ export const assetCriticalityRouteHelpersFactory = ( .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .expect(expectStatusCode); }, + bulkUpload: async ( + records: CreateAssetCriticalityRecord[], + { expectStatusCode }: { expectStatusCode: number } = { expectStatusCode: 200 } + ) => { + return supertest + .post(routeWithNamespace(ASSET_CRITICALITY_PUBLIC_BULK_UPLOAD_URL, namespace)) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.public.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send({ records }) + .expect(expectStatusCode); + }, uploadCsv: async ( fileContent: string | Buffer, { expectStatusCode }: { expectStatusCode: number } = { expectStatusCode: 200 } From 06f773934a1b3dc44355563cf4ff2274f3d325eb Mon Sep 17 00:00:00 2001 From: Ryan Keairns Date: Wed, 19 Jun 2024 09:46:20 -0700 Subject: [PATCH 124/127] [ES|QL] Set custom highlight colors for suggest widget (#186476) ## Summary Set custom theme colors for highlights in the suggest widget. *Dark mode* ![CleanShot 2024-06-19 at 08 10 32@2x](https://github.com/elastic/kibana/assets/446285/ced95d75-a5c5-4780-a9f8-188e2432ee31) *Light mode* ![CleanShot 2024-06-19 at 08 09 40@2x](https://github.com/elastic/kibana/assets/446285/7d3c6292-a9f3-4bb4-a4f9-df6fa8274c39) ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- packages/kbn-monaco/src/esql/lib/esql_theme.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/kbn-monaco/src/esql/lib/esql_theme.ts b/packages/kbn-monaco/src/esql/lib/esql_theme.ts index c88a8fc02b26d..80f9fc5400989 100644 --- a/packages/kbn-monaco/src/esql/lib/esql_theme.ts +++ b/packages/kbn-monaco/src/esql/lib/esql_theme.ts @@ -145,7 +145,9 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'editor.selectionHighlightBorder': euiThemeVars.euiColorLightShade, 'editorSuggestWidget.background': euiThemeVars.euiColorEmptyShade, 'editorSuggestWidget.border': euiThemeVars.euiColorEmptyShade, + 'editorSuggestWidget.focusHighlightForeground': euiThemeVars.euiColorEmptyShade, 'editorSuggestWidget.foreground': euiThemeVars.euiTextColor, + 'editorSuggestWidget.highlightForeground': euiThemeVars.euiColorPrimary, 'editorSuggestWidget.selectedBackground': euiThemeVars.euiColorPrimary, 'editorSuggestWidget.selectedForeground': euiThemeVars.euiColorEmptyShade, }, From 57891ff3534781bd558b680bc511427646c774c2 Mon Sep 17 00:00:00 2001 From: Davis McPhee Date: Wed, 19 Jun 2024 14:17:26 -0300 Subject: [PATCH 125/127] [Discover] Add support for contextual awareness functional tests (#185905) ## Summary This PR adds functional test support for the Discover contextual awareness framework, and adds tests for the initial `getCellRenderers` extension point using example profiles. To support this, this PR introduces a new YAML setting called `discover.experimental.enabledProfiles` which can be used to selectively enable profiles both for functional testing and demoing WIP profiles that aren't yet ready for GA. Example usage: ```yml discover.experimental.enabledProfiles: ['example-root-profile', 'example-data-source-profile', 'example-document-profile'] ``` Flaky test runs: - Stateful x50: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6304 - Serverless Observability x50: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6305 - Serverless Search x50: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6306 - Serverless Security x50: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6307 Resolves #184699. ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .buildkite/ftr_configs.yml | 4 + src/plugins/discover/common/config.ts | 3 +- .../context_awareness/__mocks__/index.ts | 21 +-- .../example_data_source_profile/index.ts | 9 ++ .../example_data_source_profile/profile.tsx | 83 ++++++++++++ .../example_document_profile/index.ts | 9 ++ .../example_document_profile/profile.ts | 32 +++++ .../example_root_pofile/index.ts | 9 ++ .../example_root_pofile/profile.tsx | 42 ++++++ .../profile_providers/index.ts | 9 ++ .../log_document_profile/profile.ts | 2 +- .../logs_data_source_profile/profile.ts | 2 +- .../profile_provider_services.ts | 0 .../register_profile_providers.test.ts | 117 +++++++++++++++++ .../register_profile_providers.ts | 85 ++++++++++++ .../context_awareness/profile_service.ts | 45 +++---- .../profiles/data_source_profile.ts | 12 +- .../profiles/document_profile.ts | 12 +- .../profiles/example_profiles.tsx | 123 ------------------ .../profiles/root_profile.ts | 12 +- src/plugins/discover/public/plugin.tsx | 63 ++++----- .../context_awareness/_data_source_profile.ts | 97 ++++++++++++++ .../context_awareness/_root_profile.ts | 52 ++++++++ .../apps/discover/context_awareness/config.ts | 26 ++++ .../apps/discover/context_awareness/index.ts | 39 ++++++ .../discover/context_awareness/data.json.gz | Bin 0 -> 351 bytes .../discover/context_awareness/mappings.json | 76 +++++++++++ .../discover/context_awareness.json | 49 +++++++ .../test_suites/core_plugins/rendering.ts | 1 + .../context_awareness/_data_source_profile.ts | 88 +++++++++++++ .../context_awareness/_root_profile.ts | 47 +++++++ .../discover/context_awareness/index.ts | 40 ++++++ .../observability/config.context_awareness.ts | 22 ++++ .../search/config.context_awareness.ts | 22 ++++ .../security/config.context_awareness.ts | 22 ++++ 35 files changed, 1072 insertions(+), 203 deletions(-) create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/index.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/index.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/index.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/index.ts rename src/plugins/discover/public/context_awareness/{profiles => profile_providers}/profile_provider_services.ts (100%) create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts create mode 100644 src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts delete mode 100644 src/plugins/discover/public/context_awareness/profiles/example_profiles.tsx create mode 100644 test/functional/apps/discover/context_awareness/_data_source_profile.ts create mode 100644 test/functional/apps/discover/context_awareness/_root_profile.ts create mode 100644 test/functional/apps/discover/context_awareness/config.ts create mode 100644 test/functional/apps/discover/context_awareness/index.ts create mode 100644 test/functional/fixtures/es_archiver/discover/context_awareness/data.json.gz create mode 100644 test/functional/fixtures/es_archiver/discover/context_awareness/mappings.json create mode 100644 test/functional/fixtures/kbn_archiver/discover/context_awareness.json create mode 100644 x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/_data_source_profile.ts create mode 100644 x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/_root_profile.ts create mode 100644 x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/index.ts create mode 100644 x-pack/test_serverless/functional/test_suites/observability/config.context_awareness.ts create mode 100644 x-pack/test_serverless/functional/test_suites/search/config.context_awareness.ts create mode 100644 x-pack/test_serverless/functional/test_suites/security/config.context_awareness.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 55f23715e3468..8e558458feb04 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -127,6 +127,7 @@ enabled: - test/functional/apps/discover/group6/config.ts - test/functional/apps/discover/group7/config.ts - test/functional/apps/discover/group8/config.ts + - test/functional/apps/discover/context_awareness/config.ts - test/functional/apps/getting_started/config.ts - test/functional/apps/home/config.ts - test/functional/apps/kibana_overview/config.ts @@ -426,6 +427,7 @@ enabled: - x-pack/test_serverless/functional/test_suites/observability/config.ts - x-pack/test_serverless/functional/test_suites/observability/config.examples.ts - x-pack/test_serverless/functional/test_suites/observability/config.saved_objects_management.ts + - x-pack/test_serverless/functional/test_suites/observability/config.context_awareness.ts - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group1.ts - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group2.ts - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group3.ts @@ -438,6 +440,7 @@ enabled: - x-pack/test_serverless/functional/test_suites/search/config.examples.ts - x-pack/test_serverless/functional/test_suites/search/config.screenshots.ts - x-pack/test_serverless/functional/test_suites/search/config.saved_objects_management.ts + - x-pack/test_serverless/functional/test_suites/search/config.context_awareness.ts - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group1.ts - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group2.ts - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group3.ts @@ -449,6 +452,7 @@ enabled: - x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.basic.ts - x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.essentials.ts - x-pack/test_serverless/functional/test_suites/security/config.saved_objects_management.ts + - x-pack/test_serverless/functional/test_suites/security/config.context_awareness.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group1.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group2.ts - x-pack/test_serverless/functional/test_suites/security/common_configs/config.group3.ts diff --git a/src/plugins/discover/common/config.ts b/src/plugins/discover/common/config.ts index f3afc0ebf08be..272f81b77d5a8 100644 --- a/src/plugins/discover/common/config.ts +++ b/src/plugins/discover/common/config.ts @@ -13,9 +13,10 @@ export const configSchema = schema.object({ experimental: schema.maybe( schema.object({ ruleFormV2Enabled: schema.maybe(schema.boolean({ defaultValue: false })), + enabledProfiles: schema.maybe(schema.arrayOf(schema.string(), { defaultValue: [] })), }) ), }); export type ConfigSchema = TypeOf; -export type ExperimentalFeatures = ConfigSchema['experimental']; +export type ExperimentalFeatures = NonNullable; diff --git a/src/plugins/discover/public/context_awareness/__mocks__/index.ts b/src/plugins/discover/public/context_awareness/__mocks__/index.ts index c13dd80676148..fbdb13a2e5648 100644 --- a/src/plugins/discover/public/context_awareness/__mocks__/index.ts +++ b/src/plugins/discover/public/context_awareness/__mocks__/index.ts @@ -19,10 +19,12 @@ import { RootProfileService, SolutionType, } from '../profiles'; -import { createProfileProviderServices } from '../profiles/profile_provider_services'; +import { createProfileProviderServices } from '../profile_providers/profile_provider_services'; import { ProfilesManager } from '../profiles_manager'; -export const createContextAwarenessMocks = () => { +export const createContextAwarenessMocks = ({ + shouldRegisterProviders = true, +}: { shouldRegisterProviders?: boolean } = {}) => { const rootProfileProviderMock: RootProfileProvider = { profileId: 'root-profile', profile: { @@ -92,15 +94,15 @@ export const createContextAwarenessMocks = () => { const records = getDataTableRecords(dataViewWithTimefieldMock); const contextRecordMock = records[0]; const contextRecordMock2 = records[1]; - const rootProfileServiceMock = new RootProfileService(); - rootProfileServiceMock.registerProvider(rootProfileProviderMock); - const dataSourceProfileServiceMock = new DataSourceProfileService(); - dataSourceProfileServiceMock.registerProvider(dataSourceProfileProviderMock); - const documentProfileServiceMock = new DocumentProfileService(); - documentProfileServiceMock.registerProvider(documentProfileProviderMock); + + if (shouldRegisterProviders) { + rootProfileServiceMock.registerProvider(rootProfileProviderMock); + dataSourceProfileServiceMock.registerProvider(dataSourceProfileProviderMock); + documentProfileServiceMock.registerProvider(documentProfileProviderMock); + } const profilesManagerMock = new ProfilesManager( rootProfileServiceMock, @@ -114,6 +116,9 @@ export const createContextAwarenessMocks = () => { rootProfileProviderMock, dataSourceProfileProviderMock, documentProfileProviderMock, + rootProfileServiceMock, + dataSourceProfileServiceMock, + documentProfileServiceMock, contextRecordMock, contextRecordMock2, profilesManagerMock, diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/index.ts new file mode 100644 index 0000000000000..032da55d4f6d0 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/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 { exampleDataSourceProfileProvider } from './profile'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx b/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx new file mode 100644 index 0000000000000..080c2ffed222b --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_data_source_profile/profile.tsx @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { EuiBadge } from '@elastic/eui'; +import type { DataTableRecord } from '@kbn/discover-utils'; +import { isOfAggregateQueryType } from '@kbn/es-query'; +import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; +import { euiThemeVars } from '@kbn/ui-theme'; +import { capitalize } from 'lodash'; +import React from 'react'; +import { DataSourceType, isDataSourceType } from '../../../../common/data_sources'; +import { DataSourceCategory, DataSourceProfileProvider } from '../../profiles'; + +export const exampleDataSourceProfileProvider: DataSourceProfileProvider = { + profileId: 'example-data-source-profile', + profile: { + getCellRenderers: (prev) => () => ({ + ...prev(), + 'log.level': (props) => { + const level = getFieldValue(props.row, 'log.level'); + + if (!level) { + return ( + + (None) + + ); + } + + const levelMap: Record = { + info: 'primary', + debug: 'default', + error: 'danger', + }; + + return ( + + {capitalize(level)} + + ); + }, + }), + }, + resolve: (params) => { + let indexPattern: string | undefined; + + if (isDataSourceType(params.dataSource, DataSourceType.Esql)) { + if (!isOfAggregateQueryType(params.query)) { + return { isMatch: false }; + } + + indexPattern = getIndexPatternFromESQLQuery(params.query.esql); + } else if (isDataSourceType(params.dataSource, DataSourceType.DataView) && params.dataView) { + indexPattern = params.dataView.getIndexPattern(); + } + + if (indexPattern !== 'my-example-logs') { + return { isMatch: false }; + } + + return { + isMatch: true, + context: { category: DataSourceCategory.Logs }, + }; + }, +}; + +const getFieldValue = (record: DataTableRecord, field: string) => { + const value = record.flattened[field]; + return Array.isArray(value) ? value[0] : value; +}; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/index.ts new file mode 100644 index 0000000000000..dab5364d8af3e --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/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 { exampleDocumentProfileProvider } from './profile'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts b/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.ts new file mode 100644 index 0000000000000..303efa103e327 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_document_profile/profile.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 type { DataTableRecord } from '@kbn/discover-utils'; +import { DocumentProfileProvider, DocumentType } from '../../profiles'; + +export const exampleDocumentProfileProvider: DocumentProfileProvider = { + profileId: 'example-document-profile', + profile: {}, + resolve: (params) => { + if (getFieldValue(params.record, 'data_stream.type') !== 'logs') { + return { isMatch: false }; + } + + return { + isMatch: true, + context: { + type: DocumentType.Log, + }, + }; + }, +}; + +const getFieldValue = (record: DataTableRecord, field: string) => { + const value = record.flattened[field]; + return Array.isArray(value) ? value[0] : value; +}; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/index.ts new file mode 100644 index 0000000000000..53f4cdc955db4 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/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 { exampleRootProfileProvider } from './profile'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx b/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx new file mode 100644 index 0000000000000..389059c518217 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/example_root_pofile/profile.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { EuiBadge } from '@elastic/eui'; +import type { DataTableRecord } from '@kbn/discover-utils'; +import React from 'react'; +import { RootProfileProvider, SolutionType } from '../../profiles'; + +export const exampleRootProfileProvider: RootProfileProvider = { + profileId: 'example-root-profile', + profile: { + getCellRenderers: (prev) => () => ({ + ...prev(), + '@timestamp': (props) => { + const timestamp = getFieldValue(props.row, '@timestamp'); + + return ( + + {timestamp} + + ); + }, + }), + }, + resolve: (params) => { + if (params.solutionNavId != null) { + return { isMatch: false }; + } + + return { isMatch: true, context: { solutionType: SolutionType.Default } }; + }, +}; + +const getFieldValue = (record: DataTableRecord, field: string) => { + const value = record.flattened[field]; + return Array.isArray(value) ? value[0] : value; +}; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/index.ts b/src/plugins/discover/public/context_awareness/profile_providers/index.ts new file mode 100644 index 0000000000000..1a5979f5a37f8 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/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 { registerProfileProviders } from './register_profile_providers'; diff --git a/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts index 7c1da0cef45cd..2d03c9e35398a 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts +++ b/src/plugins/discover/public/context_awareness/profile_providers/log_document_profile/profile.ts @@ -8,7 +8,7 @@ import { DataTableRecord } from '@kbn/discover-utils'; import { DocumentProfileProvider, DocumentType } from '../../profiles'; -import { ProfileProviderServices } from '../../profiles/profile_provider_services'; +import { ProfileProviderServices } from '../profile_provider_services'; export const createLogDocumentProfileProvider = ( services: ProfileProviderServices diff --git a/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts index 1ce42c6d1ffd1..e4a12aa9e4baf 100644 --- a/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts +++ b/src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile/profile.ts @@ -14,7 +14,7 @@ import { DataSourceProfileProvider, DataSourceProfileProviderParams, } from '../../profiles'; -import { ProfileProviderServices } from '../../profiles/profile_provider_services'; +import { ProfileProviderServices } from '../profile_provider_services'; export const createLogsDataSourceProfileProvider = ( services: ProfileProviderServices diff --git a/src/plugins/discover/public/context_awareness/profiles/profile_provider_services.ts b/src/plugins/discover/public/context_awareness/profile_providers/profile_provider_services.ts similarity index 100% rename from src/plugins/discover/public/context_awareness/profiles/profile_provider_services.ts rename to src/plugins/discover/public/context_awareness/profile_providers/profile_provider_services.ts diff --git a/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts new file mode 100644 index 0000000000000..c58726ecc1c11 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.test.ts @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { createEsqlDataSource } from '../../../common/data_sources'; +import { createContextAwarenessMocks } from '../__mocks__'; +import { exampleDataSourceProfileProvider } from './example_data_source_profile'; +import { exampleDocumentProfileProvider } from './example_document_profile'; +import { exampleRootProfileProvider } from './example_root_pofile'; +import { + registerEnabledProfileProviders, + registerProfileProviders, +} from './register_profile_providers'; + +describe('registerEnabledProfileProviders', () => { + it('should register enabled profile providers', async () => { + const { rootProfileServiceMock, rootProfileProviderMock } = createContextAwarenessMocks({ + shouldRegisterProviders: false, + }); + registerEnabledProfileProviders({ + profileService: rootProfileServiceMock, + availableProviders: [rootProfileProviderMock], + enabledProfileIds: ['root-profile'], + }); + const context = await rootProfileServiceMock.resolve({ solutionNavId: null }); + expect(rootProfileServiceMock.getProfile(context)).toBe(rootProfileProviderMock.profile); + }); + + it('should not register disabled profile providers', async () => { + const { rootProfileServiceMock, rootProfileProviderMock } = createContextAwarenessMocks({ + shouldRegisterProviders: false, + }); + registerEnabledProfileProviders({ + profileService: rootProfileServiceMock, + availableProviders: [rootProfileProviderMock], + enabledProfileIds: [], + }); + const context = await rootProfileServiceMock.resolve({ solutionNavId: null }); + expect(rootProfileServiceMock.getProfile(context)).not.toBe(rootProfileProviderMock.profile); + }); +}); + +describe('registerProfileProviders', () => { + it('should register enabled experimental profile providers', async () => { + const { rootProfileServiceMock, dataSourceProfileServiceMock, documentProfileServiceMock } = + createContextAwarenessMocks({ + shouldRegisterProviders: false, + }); + registerProfileProviders({ + rootProfileService: rootProfileServiceMock, + dataSourceProfileService: dataSourceProfileServiceMock, + documentProfileService: documentProfileServiceMock, + experimentalProfileIds: [ + exampleRootProfileProvider.profileId, + exampleDataSourceProfileProvider.profileId, + exampleDocumentProfileProvider.profileId, + ], + }); + const rootContext = await rootProfileServiceMock.resolve({ solutionNavId: null }); + const dataSourceContext = await dataSourceProfileServiceMock.resolve({ + dataSource: createEsqlDataSource(), + query: { esql: 'from my-example-logs' }, + }); + const documentContext = documentProfileServiceMock.resolve({ + record: { + id: 'test', + flattened: { 'data_stream.type': 'logs' }, + raw: {}, + }, + }); + expect(rootProfileServiceMock.getProfile(rootContext)).toBe(exampleRootProfileProvider.profile); + expect(dataSourceProfileServiceMock.getProfile(dataSourceContext)).toBe( + exampleDataSourceProfileProvider.profile + ); + expect(documentProfileServiceMock.getProfile(documentContext)).toBe( + exampleDocumentProfileProvider.profile + ); + }); + + it('should not register disabled experimental profile providers', async () => { + const { rootProfileServiceMock, dataSourceProfileServiceMock, documentProfileServiceMock } = + createContextAwarenessMocks({ + shouldRegisterProviders: false, + }); + registerProfileProviders({ + rootProfileService: rootProfileServiceMock, + dataSourceProfileService: dataSourceProfileServiceMock, + documentProfileService: documentProfileServiceMock, + experimentalProfileIds: [], + }); + const rootContext = await rootProfileServiceMock.resolve({ solutionNavId: null }); + const dataSourceContext = await dataSourceProfileServiceMock.resolve({ + dataSource: createEsqlDataSource(), + query: { esql: 'from my-example-logs' }, + }); + const documentContext = documentProfileServiceMock.resolve({ + record: { + id: 'test', + flattened: { 'data_stream.type': 'logs' }, + raw: {}, + }, + }); + expect(rootProfileServiceMock.getProfile(rootContext)).not.toBe( + exampleRootProfileProvider.profile + ); + expect(dataSourceProfileServiceMock.getProfile(dataSourceContext)).not.toBe( + exampleDataSourceProfileProvider.profile + ); + expect(documentProfileServiceMock.getProfile(documentContext)).not.toBe( + exampleDocumentProfileProvider.profile + ); + }); +}); diff --git a/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts new file mode 100644 index 0000000000000..1f4f2fbb7d931 --- /dev/null +++ b/src/plugins/discover/public/context_awareness/profile_providers/register_profile_providers.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { uniq } from 'lodash'; +import type { + DataSourceProfileService, + DocumentProfileService, + RootProfileService, +} from '../profiles'; +import type { BaseProfileProvider, BaseProfileService } from '../profile_service'; +import { exampleDataSourceProfileProvider } from './example_data_source_profile'; +import { exampleDocumentProfileProvider } from './example_document_profile'; +import { exampleRootProfileProvider } from './example_root_pofile'; +import { createLogsDataSourceProfileProvider } from './logs_data_source_profile'; +import { createLogDocumentProfileProvider } from './log_document_profile'; +import { createProfileProviderServices } from './profile_provider_services'; + +export const registerProfileProviders = ({ + rootProfileService, + dataSourceProfileService, + documentProfileService, + experimentalProfileIds, +}: { + rootProfileService: RootProfileService; + dataSourceProfileService: DataSourceProfileService; + documentProfileService: DocumentProfileService; + experimentalProfileIds: string[]; +}) => { + const providerServices = createProfileProviderServices(); + const logsDataSourceProfileProvider = createLogsDataSourceProfileProvider(providerServices); + const logsDocumentProfileProvider = createLogDocumentProfileProvider(providerServices); + const rootProfileProviders = [exampleRootProfileProvider]; + const dataSourceProfileProviders = [ + exampleDataSourceProfileProvider, + logsDataSourceProfileProvider, + ]; + const documentProfileProviders = [exampleDocumentProfileProvider, logsDocumentProfileProvider]; + const enabledProfileIds = uniq([ + logsDataSourceProfileProvider.profileId, + logsDocumentProfileProvider.profileId, + ...experimentalProfileIds, + ]); + + registerEnabledProfileProviders({ + profileService: rootProfileService, + availableProviders: rootProfileProviders, + enabledProfileIds, + }); + + registerEnabledProfileProviders({ + profileService: dataSourceProfileService, + availableProviders: dataSourceProfileProviders, + enabledProfileIds, + }); + + registerEnabledProfileProviders({ + profileService: documentProfileService, + availableProviders: documentProfileProviders, + enabledProfileIds, + }); +}; + +export const registerEnabledProfileProviders = < + TProvider extends BaseProfileProvider<{}>, + TService extends BaseProfileService +>({ + profileService, + availableProviders, + enabledProfileIds, +}: { + profileService: TService; + availableProviders: TProvider[]; + enabledProfileIds: string[]; +}) => { + for (const profile of availableProviders) { + if (enabledProfileIds.includes(profile.profileId)) { + profileService.registerProvider(profile); + } + } +}; diff --git a/src/plugins/discover/public/context_awareness/profile_service.ts b/src/plugins/discover/public/context_awareness/profile_service.ts index 2b43595761d19..efc143e222414 100644 --- a/src/plugins/discover/public/context_awareness/profile_service.ts +++ b/src/plugins/discover/public/context_awareness/profile_service.ts @@ -15,38 +15,33 @@ export type ResolveProfileResult = | { isMatch: true; context: TContext } | { isMatch: false }; -export type ProfileProviderMode = 'sync' | 'async'; +export type ContextWithProfileId = TContext & { profileId: string }; -export interface ProfileProvider< - TProfile extends PartialProfile, - TParams, - TContext, - TMode extends ProfileProviderMode -> { +export interface BaseProfileProvider { profileId: string; profile: ComposableProfile; +} + +export interface ProfileProvider + extends BaseProfileProvider { + resolve: (params: TParams) => ResolveProfileResult; +} + +export interface AsyncProfileProvider + extends BaseProfileProvider { resolve: ( params: TParams - ) => TMode extends 'sync' - ? ResolveProfileResult - : ResolveProfileResult | Promise>; + ) => ResolveProfileResult | Promise>; } -export type ContextWithProfileId = TContext & { profileId: string }; - const EMPTY_PROFILE = {}; -abstract class BaseProfileService< - TProfile extends PartialProfile, - TParams, - TContext, - TMode extends ProfileProviderMode -> { - protected readonly providers: Array> = []; +export abstract class BaseProfileService, TContext> { + protected readonly providers: TProvider[] = []; protected constructor(public readonly defaultContext: ContextWithProfileId) {} - public registerProvider(provider: ProfileProvider) { + public registerProvider(provider: TProvider) { this.providers.push(provider); } @@ -54,19 +49,13 @@ abstract class BaseProfileService< const provider = this.providers.find((current) => current.profileId === context.profileId); return provider?.profile ?? EMPTY_PROFILE; } - - public abstract resolve( - params: TParams - ): TMode extends 'sync' - ? ContextWithProfileId - : Promise>; } export class ProfileService< TProfile extends PartialProfile, TParams, TContext -> extends BaseProfileService { +> extends BaseProfileService, TContext> { public resolve(params: TParams) { for (const provider of this.providers) { const result = provider.resolve(params); @@ -87,7 +76,7 @@ export class AsyncProfileService< TProfile extends PartialProfile, TParams, TContext -> extends BaseProfileService { +> extends BaseProfileService, TContext> { public async resolve(params: TParams) { for (const provider of this.providers) { const result = await provider.resolve(params); diff --git a/src/plugins/discover/public/context_awareness/profiles/data_source_profile.ts b/src/plugins/discover/public/context_awareness/profiles/data_source_profile.ts index f616fef913259..1dbb3c20d8b51 100644 --- a/src/plugins/discover/public/context_awareness/profiles/data_source_profile.ts +++ b/src/plugins/discover/public/context_awareness/profiles/data_source_profile.ts @@ -9,7 +9,7 @@ import type { DataView } from '@kbn/data-views-plugin/common'; import type { AggregateQuery, Query } from '@kbn/es-query'; import type { DiscoverDataSource } from '../../../common/data_sources'; -import { AsyncProfileService } from '../profile_service'; +import { AsyncProfileProvider, AsyncProfileService } from '../profile_service'; import { Profile } from '../types'; export enum DataSourceCategory { @@ -17,6 +17,8 @@ export enum DataSourceCategory { Default = 'default', } +export type DataSourceProfile = Profile; + export interface DataSourceProfileProviderParams { dataSource?: DiscoverDataSource; dataView?: DataView; @@ -27,7 +29,11 @@ export interface DataSourceContext { category: DataSourceCategory; } -export type DataSourceProfile = Profile; +export type DataSourceProfileProvider = AsyncProfileProvider< + DataSourceProfile, + DataSourceProfileProviderParams, + DataSourceContext +>; export class DataSourceProfileService extends AsyncProfileService< DataSourceProfile, @@ -41,5 +47,3 @@ export class DataSourceProfileService extends AsyncProfileService< }); } } - -export type DataSourceProfileProvider = Parameters[0]; diff --git a/src/plugins/discover/public/context_awareness/profiles/document_profile.ts b/src/plugins/discover/public/context_awareness/profiles/document_profile.ts index 70b134da452e4..c6fd19b8f2014 100644 --- a/src/plugins/discover/public/context_awareness/profiles/document_profile.ts +++ b/src/plugins/discover/public/context_awareness/profiles/document_profile.ts @@ -8,13 +8,15 @@ import type { DataTableRecord } from '@kbn/discover-utils'; import type { Profile } from '../types'; -import { ProfileService } from '../profile_service'; +import { ProfileProvider, ProfileService } from '../profile_service'; export enum DocumentType { Log = 'log', Default = 'default', } +export type DocumentProfile = Omit; + export interface DocumentProfileProviderParams { record: DataTableRecord; } @@ -23,7 +25,11 @@ export interface DocumentContext { type: DocumentType; } -export type DocumentProfile = Omit; +export type DocumentProfileProvider = ProfileProvider< + DocumentProfile, + DocumentProfileProviderParams, + DocumentContext +>; export class DocumentProfileService extends ProfileService< DocumentProfile, @@ -37,5 +43,3 @@ export class DocumentProfileService extends ProfileService< }); } } - -export type DocumentProfileProvider = Parameters[0]; diff --git a/src/plugins/discover/public/context_awareness/profiles/example_profiles.tsx b/src/plugins/discover/public/context_awareness/profiles/example_profiles.tsx deleted file mode 100644 index 3835337b25304..0000000000000 --- a/src/plugins/discover/public/context_awareness/profiles/example_profiles.tsx +++ /dev/null @@ -1,123 +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 { EuiBadge } from '@elastic/eui'; -import { - DataTableRecord, - getMessageFieldWithFallbacks, - LogDocumentOverview, -} from '@kbn/discover-utils'; -import { isOfAggregateQueryType } from '@kbn/es-query'; -import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; -import { euiThemeVars } from '@kbn/ui-theme'; -import { capitalize } from 'lodash'; -import React from 'react'; -import { DataSourceType, isDataSourceType } from '../../../common/data_sources'; -import { DataSourceCategory, DataSourceProfileProvider } from './data_source_profile'; -import { DocumentProfileProvider, DocumentType } from './document_profile'; -import { RootProfileProvider, SolutionType } from './root_profile'; - -export const o11yRootProfileProvider: RootProfileProvider = { - profileId: 'o11y-root-profile', - profile: {}, - resolve: (params) => { - if (params.solutionNavId === 'oblt') { - return { - isMatch: true, - context: { - solutionType: SolutionType.Observability, - }, - }; - } - - return { isMatch: false }; - }, -}; - -export const logsDataSourceProfileProvider: DataSourceProfileProvider = { - profileId: 'logs-data-source-profile', - profile: { - getCellRenderers: (prev) => () => ({ - ...prev(), - '@timestamp': (props) => { - const timestamp = getFieldValue(props.row, '@timestamp'); - return ( - - {timestamp} - - ); - }, - 'log.level': (props) => { - const level = getFieldValue(props.row, 'log.level'); - if (!level) { - return (None); - } - const levelMap: Record = { - info: 'primary', - debug: 'default', - error: 'danger', - }; - return ( - - {capitalize(level)} - - ); - }, - message: (props) => { - const { value } = getMessageFieldWithFallbacks( - props.row.flattened as unknown as LogDocumentOverview - ); - return value || (None); - }, - }), - }, - resolve: (params) => { - let indices: string[] = []; - - if (isDataSourceType(params.dataSource, DataSourceType.Esql)) { - if (!isOfAggregateQueryType(params.query)) { - return { isMatch: false }; - } - - indices = getIndexPatternFromESQLQuery(params.query.esql).split(','); - } else if (isDataSourceType(params.dataSource, DataSourceType.DataView) && params.dataView) { - indices = params.dataView.getIndexPattern().split(','); - } - - if (indices.every((index) => index.startsWith('logs-'))) { - return { - isMatch: true, - context: { category: DataSourceCategory.Logs }, - }; - } - - return { isMatch: false }; - }, -}; - -export const logDocumentProfileProvider: DocumentProfileProvider = { - profileId: 'log-document-profile', - profile: {}, - resolve: (params) => { - if (getFieldValue(params.record, 'data_stream.type') === 'logs') { - return { - isMatch: true, - context: { - type: DocumentType.Log, - }, - }; - } - - return { isMatch: false }; - }, -}; - -const getFieldValue = (record: DataTableRecord, field: string) => { - const value = record.flattened[field]; - return Array.isArray(value) ? value[0] : value; -}; diff --git a/src/plugins/discover/public/context_awareness/profiles/root_profile.ts b/src/plugins/discover/public/context_awareness/profiles/root_profile.ts index 42497fe680c5c..77bf9d9d63b0b 100644 --- a/src/plugins/discover/public/context_awareness/profiles/root_profile.ts +++ b/src/plugins/discover/public/context_awareness/profiles/root_profile.ts @@ -7,7 +7,7 @@ */ import type { Profile } from '../types'; -import { AsyncProfileService } from '../profile_service'; +import { AsyncProfileProvider, AsyncProfileService } from '../profile_service'; export enum SolutionType { Observability = 'oblt', @@ -16,6 +16,8 @@ export enum SolutionType { Default = 'default', } +export type RootProfile = Profile; + export interface RootProfileProviderParams { solutionNavId?: string | null; } @@ -24,7 +26,11 @@ export interface RootContext { solutionType: SolutionType; } -export type RootProfile = Profile; +export type RootProfileProvider = AsyncProfileProvider< + RootProfile, + RootProfileProviderParams, + RootContext +>; export class RootProfileService extends AsyncProfileService< RootProfile, @@ -38,5 +44,3 @@ export class RootProfileService extends AsyncProfileService< }); } } - -export type RootProfileProvider = Parameters[0]; diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index 4f1ae2a32634e..78da5820f1ddb 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -21,6 +21,7 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; import { ENABLE_ESQL } from '@kbn/esql-utils'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; import { TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils'; +import { once } from 'lodash'; import { PLUGIN_ID } from '../common'; import { registerFeature } from './register_feature'; import { buildServices, UrlTracker } from './build_services'; @@ -56,10 +57,7 @@ import { ProfilesManager, RootProfileService, } from './context_awareness'; -import { createProfileProviderServices } from './context_awareness/profiles/profile_provider_services'; import { DiscoverSetup, DiscoverSetupPlugins, DiscoverStart, DiscoverStartPlugins } from './types'; -import { createLogsDataSourceProfileProvider } from './context_awareness/profile_providers/logs_data_source_profile'; -import { createLogDocumentProfileProvider } from './context_awareness/profile_providers/log_document_profile'; /** * Contains Discover, one of the oldest parts of Kibana @@ -68,16 +66,11 @@ import { createLogDocumentProfileProvider } from './context_awareness/profile_pr export class DiscoverPlugin implements Plugin { - private readonly rootProfileService = new RootProfileService(); - private readonly dataSourceProfileService = new DataSourceProfileService(); - private readonly documentProfileService = new DocumentProfileService(); private readonly appStateUpdater = new BehaviorSubject(() => ({})); private readonly historyService = new HistoryService(); private readonly inlineTopNav: Map = new Map([[null, defaultCustomizationContext.inlineTopNav]]); - private readonly experimentalFeatures: ExperimentalFeatures = { - ruleFormV2Enabled: false, - }; + private readonly experimentalFeatures: ExperimentalFeatures; private scopedHistory?: ScopedHistory; private urlTracker?: UrlTracker; @@ -87,8 +80,12 @@ export class DiscoverPlugin private singleDocLocator?: DiscoverSingleDocLocator; constructor(private readonly initializerContext: PluginInitializerContext) { - this.experimentalFeatures = - initializerContext.config.get().experimental ?? this.experimentalFeatures; + const experimental = this.initializerContext.config.get().experimental; + + this.experimentalFeatures = { + ruleFormV2Enabled: experimental?.ruleFormV2Enabled ?? false, + enabledProfiles: experimental?.enabledProfiles ?? [], + }; } setup( @@ -184,7 +181,7 @@ export class DiscoverPlugin history: this.historyService.getHistory(), scopedHistory: this.scopedHistory, urlTracker: this.urlTracker!, - profilesManager: this.createProfilesManager(), + profilesManager: await this.createProfilesManager(), setHeaderActionMenu: params.setHeaderActionMenu, }); @@ -267,8 +264,6 @@ export class DiscoverPlugin } start(core: CoreStart, plugins: DiscoverStartPlugins): DiscoverStart { - this.registerProfiles(); - const viewSavedSearchAction = new ViewSavedSearchAction(core.application, this.locator!); plugins.uiActions.addTriggerAction('CONTEXT_MENU_TRIGGER', viewSavedSearchAction); @@ -304,22 +299,31 @@ export class DiscoverPlugin } } - private registerProfiles() { - const providerServices = createProfileProviderServices(); + private createProfileServices = once(async () => { + const { registerProfileProviders } = await import('./context_awareness/profile_providers'); + const rootProfileService = new RootProfileService(); + const dataSourceProfileService = new DataSourceProfileService(); + const documentProfileService = new DocumentProfileService(); + const experimentalProfileIds = this.experimentalFeatures.enabledProfiles ?? []; + + registerProfileProviders({ + rootProfileService, + dataSourceProfileService, + documentProfileService, + experimentalProfileIds, + }); - this.dataSourceProfileService.registerProvider( - createLogsDataSourceProfileProvider(providerServices) - ); - this.documentProfileService.registerProvider( - createLogDocumentProfileProvider(providerServices) - ); - } + return { rootProfileService, dataSourceProfileService, documentProfileService }; + }); + + private async createProfilesManager() { + const { rootProfileService, dataSourceProfileService, documentProfileService } = + await this.createProfileServices(); - private createProfilesManager() { return new ProfilesManager( - this.rootProfileService, - this.dataSourceProfileService, - this.documentProfileService + rootProfileService, + dataSourceProfileService, + documentProfileService ); } @@ -334,7 +338,7 @@ export class DiscoverPlugin private getDiscoverServices = ( core: CoreStart, plugins: DiscoverStartPlugins, - profilesManager = this.createProfilesManager() + profilesManager: ProfilesManager ) => { return buildServices({ core, @@ -360,7 +364,8 @@ export class DiscoverPlugin const getDiscoverServicesInternal = async () => { const [coreStart, deps] = await core.getStartServices(); - return this.getDiscoverServices(coreStart, deps); + const profilesManager = await this.createProfilesManager(); + return this.getDiscoverServices(coreStart, deps, profilesManager); }; const factory = new SearchEmbeddableFactory(getStartServices, getDiscoverServicesInternal); diff --git a/test/functional/apps/discover/context_awareness/_data_source_profile.ts b/test/functional/apps/discover/context_awareness/_data_source_profile.ts new file mode 100644 index 0000000000000..d203f33c887e8 --- /dev/null +++ b/test/functional/apps/discover/context_awareness/_data_source_profile.ts @@ -0,0 +1,97 @@ +/* + * Copyright 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 kbnRison from '@kbn/rison'; +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'timePicker', 'discover', 'unifiedFieldList']); + const testSubjects = getService('testSubjects'); + const dataViews = getService('dataViews'); + + describe('data source profile', () => { + describe('ES|QL mode', () => { + describe('cell renderers', () => { + it('should render custom @timestamp but not custom log.level', async () => { + const state = kbnRison.encode({ + dataSource: { type: 'esql' }, + query: { esql: 'from my-example-* | sort @timestamp desc' }, + }); + await PageObjects.common.navigateToApp('discover', { + hash: `/?_a=${state}`, + }); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp'); + expect(timestamps).to.have.length(6); + expect(await timestamps[0].getVisibleText()).to.be('2024-06-10T16:30:00.000Z'); + expect(await timestamps[5].getVisibleText()).to.be('2024-06-10T14:00:00.000Z'); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel', 2500); + expect(logLevels).to.have.length(0); + }); + + it('should render custom @timestamp and custom log.level', async () => { + const state = kbnRison.encode({ + dataSource: { type: 'esql' }, + query: { esql: 'from my-example-logs | sort @timestamp desc' }, + }); + await PageObjects.common.navigateToApp('discover', { + hash: `/?_a=${state}`, + }); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp'); + expect(timestamps).to.have.length(3); + expect(await timestamps[0].getVisibleText()).to.be('2024-06-10T16:00:00.000Z'); + expect(await timestamps[2].getVisibleText()).to.be('2024-06-10T14:00:00.000Z'); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel'); + expect(logLevels).to.have.length(3); + expect(await logLevels[0].getVisibleText()).to.be('Debug'); + expect(await logLevels[2].getVisibleText()).to.be('Info'); + }); + }); + }); + + describe('data view mode', () => { + describe('cell renderers', () => { + it('should render custom @timestamp but not custom log.level', async () => { + await PageObjects.common.navigateToApp('discover'); + await dataViews.switchTo('my-example-*'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp'); + expect(timestamps).to.have.length(6); + expect(await timestamps[0].getVisibleText()).to.be('2024-06-10T16:30:00.000Z'); + expect(await timestamps[5].getVisibleText()).to.be('2024-06-10T14:00:00.000Z'); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel', 2500); + expect(logLevels).to.have.length(0); + }); + + it('should render custom @timestamp and custom log.level', async () => { + await PageObjects.common.navigateToApp('discover'); + await dataViews.switchTo('my-example-logs'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp'); + expect(timestamps).to.have.length(3); + expect(await timestamps[0].getVisibleText()).to.be('2024-06-10T16:00:00.000Z'); + expect(await timestamps[2].getVisibleText()).to.be('2024-06-10T14:00:00.000Z'); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel'); + expect(logLevels).to.have.length(3); + expect(await logLevels[0].getVisibleText()).to.be('Debug'); + expect(await logLevels[2].getVisibleText()).to.be('Info'); + }); + }); + }); + }); +} diff --git a/test/functional/apps/discover/context_awareness/_root_profile.ts b/test/functional/apps/discover/context_awareness/_root_profile.ts new file mode 100644 index 0000000000000..c0bb4885699f8 --- /dev/null +++ b/test/functional/apps/discover/context_awareness/_root_profile.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 kbnRison from '@kbn/rison'; +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); + const testSubjects = getService('testSubjects'); + const dataViews = getService('dataViews'); + + describe('root profile', () => { + describe('ES|QL mode', () => { + describe('cell renderers', () => { + it('should render custom @timestamp', async () => { + const state = kbnRison.encode({ + dataSource: { type: 'esql' }, + query: { esql: 'from my-example-* | sort @timestamp desc' }, + }); + await PageObjects.common.navigateToApp('discover', { + hash: `/?_a=${state}`, + }); + await PageObjects.discover.waitUntilSearchingHasFinished(); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp'); + expect(timestamps).to.have.length(6); + expect(await timestamps[0].getVisibleText()).to.be('2024-06-10T16:30:00.000Z'); + expect(await timestamps[5].getVisibleText()).to.be('2024-06-10T14:00:00.000Z'); + }); + }); + }); + + describe('data view mode', () => { + describe('cell renderers', () => { + it('should render custom @timestamp', async () => { + await PageObjects.common.navigateToApp('discover'); + await dataViews.switchTo('my-example-*'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp'); + expect(timestamps).to.have.length(6); + expect(await timestamps[0].getVisibleText()).to.be('2024-06-10T16:30:00.000Z'); + expect(await timestamps[5].getVisibleText()).to.be('2024-06-10T14:00:00.000Z'); + }); + }); + }); + }); +} diff --git a/test/functional/apps/discover/context_awareness/config.ts b/test/functional/apps/discover/context_awareness/config.ts new file mode 100644 index 0000000000000..c8e43a6bb2c9d --- /dev/null +++ b/test/functional/apps/discover/context_awareness/config.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + const baseConfig = functionalConfig.getAll(); + + return { + ...baseConfig, + testFiles: [require.resolve('.')], + kbnTestServer: { + ...baseConfig.kbnTestServer, + serverArgs: [ + ...baseConfig.kbnTestServer.serverArgs, + '--discover.experimental.enabledProfiles=["example-root-profile","example-data-source-profile","example-document-profile"]', + ], + }, + }; +} diff --git a/test/functional/apps/discover/context_awareness/index.ts b/test/functional/apps/discover/context_awareness/index.ts new file mode 100644 index 0000000000000..f280024ec7c80 --- /dev/null +++ b/test/functional/apps/discover/context_awareness/index.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['timePicker']); + const from = '2024-06-10T14:00:00.000Z'; + const to = '2024-06-10T16:30:00.000Z'; + + describe('discover/context_awareness', () => { + before(async () => { + await esArchiver.load('test/functional/fixtures/es_archiver/discover/context_awareness'); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/discover/context_awareness' + ); + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': `{ "from": "${from}", "to": "${to}"}`, + }); + }); + + after(async () => { + await esArchiver.unload('test/functional/fixtures/es_archiver/discover/context_awareness'); + await kibanaServer.importExport.unload( + 'test/functional/fixtures/kbn_archiver/discover/context_awareness' + ); + await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + }); + + loadTestFile(require.resolve('./_root_profile')); + loadTestFile(require.resolve('./_data_source_profile')); + }); +} diff --git a/test/functional/fixtures/es_archiver/discover/context_awareness/data.json.gz b/test/functional/fixtures/es_archiver/discover/context_awareness/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..cd1f670958d7d47b36a6868efc537ec09bb76939 GIT binary patch literal 351 zcmV-l0igaLiwFP!000026Sb2;Z-Ous$M1ZKm!1cyC@gZ?=G@d66BDzsU6x8KW1%gh z#psOR-IQpQi`x`PIMDZhEx#X+jRk=8I%6mRL}i3-%)*kSg<08H001bVrW#JB{m1P7 zVe$MUUV5#$KNyKJZW4mBl?m~+%~phGDYH`Tr^Xh5T(!Oy~lyIi=B)ahTY5&nm^$-BWmP}}e7CF(06es}K_i%Y# x4E{E$f`7M%?S{bpI>9l { + describe('ES|QL mode', () => { + describe('cell renderers', () => { + it('should not render custom @timestamp or log.level', async () => { + const state = kbnRison.encode({ + dataSource: { type: 'esql' }, + query: { esql: 'from my-example-* | sort @timestamp desc' }, + }); + await PageObjects.common.navigateToApp('discover', { + hash: `/?_a=${state}`, + }); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp', 2500); + expect(timestamps).to.have.length(0); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel', 2500); + expect(logLevels).to.have.length(0); + }); + + it('should not render custom @timestamp but should render custom log.level', async () => { + const state = kbnRison.encode({ + dataSource: { type: 'esql' }, + query: { esql: 'from my-example-logs | sort @timestamp desc' }, + }); + await PageObjects.common.navigateToApp('discover', { + hash: `/?_a=${state}`, + }); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp', 2500); + expect(timestamps).to.have.length(0); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel'); + expect(logLevels).to.have.length(3); + expect(await logLevels[0].getVisibleText()).to.be('Debug'); + expect(await logLevels[2].getVisibleText()).to.be('Info'); + }); + }); + }); + + describe('data view mode', () => { + describe('cell renderers', () => { + it('should not render custom @timestamp or log.level', async () => { + await PageObjects.common.navigateToApp('discover'); + await dataViews.switchTo('my-example-*'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp', 2500); + expect(timestamps).to.have.length(0); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel', 2500); + expect(logLevels).to.have.length(0); + }); + + it('should not render custom @timestamp but should render custom log.level', async () => { + await PageObjects.common.navigateToApp('discover'); + await dataViews.switchTo('my-example-logs'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp'); + await PageObjects.unifiedFieldList.clickFieldListItemAdd('log.level'); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp', 2500); + expect(timestamps).to.have.length(0); + const logLevels = await testSubjects.findAll('exampleDataSourceProfileLogLevel'); + expect(logLevels).to.have.length(3); + expect(await logLevels[0].getVisibleText()).to.be('Debug'); + expect(await logLevels[2].getVisibleText()).to.be('Info'); + }); + }); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/_root_profile.ts b/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/_root_profile.ts new file mode 100644 index 0000000000000..649d0a67ee22f --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/_root_profile.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import kbnRison from '@kbn/rison'; +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); + const testSubjects = getService('testSubjects'); + const dataViews = getService('dataViews'); + + describe('root profile', () => { + describe('ES|QL mode', () => { + describe('cell renderers', () => { + it('should not render custom @timestamp', async () => { + const state = kbnRison.encode({ + dataSource: { type: 'esql' }, + query: { esql: 'from my-example-* | sort @timestamp desc' }, + }); + await PageObjects.common.navigateToApp('discover', { + hash: `/?_a=${state}`, + }); + await PageObjects.discover.waitUntilSearchingHasFinished(); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp', 2500); + expect(timestamps).to.have.length(0); + }); + }); + }); + + describe('data view mode', () => { + describe('cell renderers', () => { + it('should not render custom @timestamp', async () => { + await PageObjects.common.navigateToApp('discover'); + await dataViews.switchTo('my-example-*'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + const timestamps = await testSubjects.findAll('exampleRootProfileTimestamp', 2500); + expect(timestamps).to.have.length(0); + }); + }); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/index.ts b/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/index.ts new file mode 100644 index 0000000000000..e6e128e4b6b59 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/discover/context_awareness/index.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['timePicker', 'svlCommonPage']); + const from = '2024-06-10T14:00:00.000Z'; + const to = '2024-06-10T16:30:00.000Z'; + + describe('discover/context_awareness', () => { + before(async () => { + await esArchiver.load('test/functional/fixtures/es_archiver/discover/context_awareness'); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/discover/context_awareness' + ); + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': `{ "from": "${from}", "to": "${to}"}`, + }); + await PageObjects.svlCommonPage.login(); + }); + + after(async () => { + await esArchiver.unload('test/functional/fixtures/es_archiver/discover/context_awareness'); + await kibanaServer.importExport.unload( + 'test/functional/fixtures/kbn_archiver/discover/context_awareness' + ); + await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + }); + + loadTestFile(require.resolve('./_root_profile')); + loadTestFile(require.resolve('./_data_source_profile')); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/observability/config.context_awareness.ts b/x-pack/test_serverless/functional/test_suites/observability/config.context_awareness.ts new file mode 100644 index 0000000000000..76362cc111e6f --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/config.context_awareness.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 { createTestConfig } from '../../config.base'; + +export default createTestConfig({ + serverlessProject: 'oblt', + testFiles: [require.resolve('../common/discover/context_awareness')], + junit: { + reportName: 'Serverless Observability Discover Context Awareness Functional Tests', + }, + kbnServerArgs: [ + '--discover.experimental.enabledProfiles=["example-root-profile","example-data-source-profile","example-document-profile"]', + ], + // include settings from project controller + // https://github.com/elastic/project-controller/blob/main/internal/project/observability/config/elasticsearch.yml + esServerArgs: ['xpack.ml.dfa.enabled=false'], +}); diff --git a/x-pack/test_serverless/functional/test_suites/search/config.context_awareness.ts b/x-pack/test_serverless/functional/test_suites/search/config.context_awareness.ts new file mode 100644 index 0000000000000..7b608c29c9f3a --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/search/config.context_awareness.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 { createTestConfig } from '../../config.base'; + +export default createTestConfig({ + serverlessProject: 'es', + testFiles: [require.resolve('../common/discover/context_awareness')], + junit: { + reportName: 'Serverless Search Discover Context Awareness Functional Tests', + }, + kbnServerArgs: [ + '--discover.experimental.enabledProfiles=["example-root-profile","example-data-source-profile","example-document-profile"]', + ], + // include settings from project controller + // https://github.com/elastic/project-controller/blob/main/internal/project/observability/config/elasticsearch.yml + esServerArgs: ['xpack.ml.dfa.enabled=false'], +}); diff --git a/x-pack/test_serverless/functional/test_suites/security/config.context_awareness.ts b/x-pack/test_serverless/functional/test_suites/security/config.context_awareness.ts new file mode 100644 index 0000000000000..6276922df83f4 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/config.context_awareness.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 { createTestConfig } from '../../config.base'; + +export default createTestConfig({ + serverlessProject: 'security', + testFiles: [require.resolve('../common/discover/context_awareness')], + junit: { + reportName: 'Serverless Security Discover Context Awareness Functional Tests', + }, + kbnServerArgs: [ + '--discover.experimental.enabledProfiles=["example-root-profile","example-data-source-profile","example-document-profile"]', + ], + // include settings from project controller + // https://github.com/elastic/project-controller/blob/main/internal/project/observability/config/elasticsearch.yml + esServerArgs: ['xpack.ml.dfa.enabled=false'], +}); From 2f4997cbfebdd6d69937d00f7f1e6e59e98f0ca6 Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Wed, 19 Jun 2024 21:04:07 +0200 Subject: [PATCH 126/127] [Lens] Legend Statistics feature (#182357) ## Summary Fixes https://github.com/elastic/kibana/issues/183887 Screenshot 2024-06-09 at 21 11 33 Screenshot 2024-06-09 at 21 11 38 - [x] popover width = 500 px - [x] new combobox legend values component added - [x] switch show value removed - [x] location and alignment is in a single for row - [x] auto legend width option to allow users to have the legend automatically size based its contents - not there yet - [x] no limit imposed of the number of values - [x] when a value is selected, list or table appears - [x] when the list is selected, label truncations is not offered and legend items should be forced to have truncation on and clamped to a single line. - [x] adds telemetry too - adds events on save if the legend statistics change: `lens_legend_stats`- triggered if any stats is in legend `lens_legend_stats_${TYPE}` - triggered for specific types, if user has 2 statistics (eg. AVG and MIN) two events are triggered. and counting how many they use `lens_legend_stats_amount_1` `lens_legend_stats_amount_2` `lens_legend_stats_amount_3` `lens_legend_stats_amount_4_7` `lens_legend_stats_amount_above_8` --------- Co-authored-by: Nick Partridge Co-authored-by: Marco Vettorello --- .../visualization_types/xy_chart.ts | 4 +- .../waffle_vis_function.test.ts | 8 +- .../public/__stories__/shared/arg_types.ts | 5 +- .../expression_partition_vis/public/mocks.ts | 4 +- .../expression_functions/legend_config.ts | 22 +- .../common/types/expression_functions.ts | 7 +- .../public/components/xy_chart.test.tsx | 9 +- .../public/components/xy_chart.tsx | 23 +- .../configurations/index.test.ts | 4 +- .../convert_to_lens/configurations/index.ts | 6 +- .../convert_to_lens/configurations/index.ts | 5 +- src/plugins/vis_types/xy/public/to_ast.ts | 5 +- .../visualizations/common/constants.ts | 33 ++- .../convert_to_lens/types/configurations.ts | 2 +- src/plugins/visualizations/common/index.ts | 5 +- .../axis/title/axis_title_settings.tsx | 101 -------- ...st.tsx => toolbar_title_settings.test.tsx} | 28 +- .../axis/title/toolbar_title_settings.tsx | 107 ++++++++ .../lens/public/shared_components/index.ts | 2 +- .../legend/layout/columns_number_setting.tsx | 8 +- .../legend/legend_settings_popover.test.tsx | 26 +- .../legend/legend_settings_popover.tsx | 243 ++++++++++++------ .../location/legend_location_settings.tsx | 4 +- .../legend/size/legend_size_settings.tsx | 2 +- .../public/shared_components/vis_label.tsx | 5 +- .../heatmap/toolbar_component.tsx | 18 +- .../partition/partition_charts_meta.ts | 5 +- .../visualizations/partition/persistence.tsx | 4 +- .../partition/render_helpers.test.ts | 18 +- .../partition/render_helpers.ts | 4 +- .../visualizations/partition/toolbar.tsx | 25 +- .../partition/visualization.test.ts | 4 +- .../xy/legend_stats_telemetry_helpers.test.ts | 113 ++++++++ .../xy/legend_stats_telemetry_helpers.ts | 49 ++++ .../public/visualizations/xy/persistence.ts | 4 +- .../public/visualizations/xy/to_expression.ts | 3 + .../visualizations/xy/visualization.test.tsx | 5 +- .../visualizations/xy/visualization.tsx | 16 +- .../axis_settings_popover.test.tsx | 2 +- .../xy_config_panel/axis_settings_popover.tsx | 18 +- .../xy/xy_config_panel/index.tsx | 225 ++++++++++++++-- .../translations/translations/fr-FR.json | 3 +- .../translations/translations/ja-JP.json | 3 +- .../translations/translations/zh-CN.json | 3 +- .../apps/lens/group6/legend_statistics.ts | 103 +++++--- .../test/functional/page_objects/lens_page.ts | 7 +- 46 files changed, 953 insertions(+), 347 deletions(-) delete mode 100644 x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.tsx rename x-pack/plugins/lens/public/shared_components/axis/title/{axis_title_settings.test.tsx => toolbar_title_settings.test.tsx} (80%) create mode 100644 x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.tsx create mode 100644 x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.test.ts create mode 100644 x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.ts diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts index a992a97a23e4b..60891ea0b1c10 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts @@ -17,7 +17,7 @@ import type { import type { DataView } from '@kbn/data-views-plugin/public'; import type { SavedObjectReference } from '@kbn/core/server'; import { AxesSettingsConfig } from '@kbn/visualizations-plugin/common'; -import type { XYLegendValue } from '@kbn/visualizations-plugin/common/constants'; +import { LegendValue } from '@elastic/charts'; import type { Chart, ChartConfig, ChartLayer } from '../types'; import { DEFAULT_LAYER_ID } from '../utils'; import { XY_ID } from './constants'; @@ -131,7 +131,7 @@ export const getXYVisualizationState = ( isVisible: false, position: 'right', showSingleSeries: false, - legendStats: ['currentAndLastValue' as XYLegendValue.CurrentAndLastValue], + legendStats: [LegendValue.CurrentAndLastValue], }, valueLabels: 'show', yLeftScale: 'linear', diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts index e5a14a37e0ffb..f3f4a3c9a144f 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts @@ -13,14 +13,12 @@ import { ValueFormats, LegendDisplay, } from '../types/expression_renderers'; -import { - ExpressionValueVisDimension, - PartitionLegendValue, -} from '@kbn/visualizations-plugin/common'; +import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common'; import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs'; import { waffleVisFunction } from './waffle_vis_function'; import { PARTITION_LABELS_VALUE, PARTITION_VIS_RENDERER_NAME } from '../constants'; import { ExecutionContext } from '@kbn/expressions-plugin/common'; +import { LegendValue } from '@elastic/charts'; describe('interpreter/functions#waffleVis', () => { const fn = functionWrapper(waffleVisFunction()); @@ -37,7 +35,7 @@ describe('interpreter/functions#waffleVis', () => { const visConfig: WaffleVisConfig = { addTooltip: true, - legendStats: [PartitionLegendValue.Value], + legendStats: [LegendValue.Value], metricsToLabels: JSON.stringify({}), legendDisplay: LegendDisplay.SHOW, legendPosition: 'right', diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/arg_types.ts b/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/arg_types.ts index 314eb3369b61d..a35e9b09f5662 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/arg_types.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/arg_types.ts @@ -6,9 +6,8 @@ * Side Public License, v 1. */ -import { Position } from '@elastic/charts'; +import { LegendValue, Position } from '@elastic/charts'; import { ArgTypes } from '@storybook/addons'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { EmptySizeRatios, LegendDisplay } from '../../../common'; import { ChartTypes } from '../../../common/types'; @@ -212,7 +211,7 @@ export const waffleArgTypes: ArgTypes = { description: 'Legend stats', type: { name: 'string', required: false }, table: { type: { summary: 'string' }, defaultValue: { summary: undefined } }, - options: [PartitionLegendValue.Value], + options: [LegendValue.Value], control: { type: 'select' }, }, }; diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts b/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts index 4f48c03f7f915..faea42ddc0b13 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { LegendValue } from '@elastic/charts'; import { Datatable } from '@kbn/expressions-plugin/public'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { BucketColumns, PartitionVisParams, @@ -382,6 +382,6 @@ export const createMockWaffleParams = (): PartitionVisParams => { }, ], }, - legendStats: [PartitionLegendValue.Value], + legendStats: [LegendValue.Value], }; }; diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/legend_config.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/legend_config.ts index e83db93c914af..c9e524dcae818 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/legend_config.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/legend_config.ts @@ -8,7 +8,7 @@ import { HorizontalAlignment, Position, VerticalAlignment } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; -import { LegendSize } from '@kbn/visualizations-plugin/common/constants'; +import { LegendLayout, LegendSize } from '@kbn/visualizations-plugin/common/constants'; import { LEGEND_CONFIG } from '../constants'; import { LegendConfigFn } from '../types'; @@ -106,6 +106,26 @@ export const legendConfigFunction: LegendConfigFn = { defaultMessage: 'Specifies the legend stats.', }), }, + title: { + types: ['string'], + help: i18n.translate('expressionXY.legendConfig.title.help', { + defaultMessage: 'Specifies the legend title.', + }), + }, + isTitleVisible: { + types: ['boolean'], + help: i18n.translate('expressionXY.legendConfig.isTitleVisible.help', { + defaultMessage: 'Specifies if the legend title is visible.', + }), + }, + layout: { + types: ['string'], + help: i18n.translate('expressionXY.legendConfig.legendLayout.help', { + defaultMessage: 'Specifies the legend layout.', + }), + options: [LegendLayout.Table, LegendLayout.List], + strict: true, + }, }, async fn(input, args, handlers) { const { legendConfigFn } = await import('./legend_config_fn'); diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index a93a8510d4506..dd4c0acbd22fc 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -16,8 +16,9 @@ import type { } from '@kbn/expressions-plugin/common'; import { LegendSize, - ExpressionValueVisDimension, XYLegendValue, + LegendLayout, + ExpressionValueVisDimension, } from '@kbn/visualizations-plugin/common'; import { EventAnnotationOutput } from '@kbn/event-annotation-plugin/common'; @@ -220,7 +221,11 @@ export interface LegendConfig { /** * metrics to display in the legend */ + legendStats?: XYLegendValue[]; + layout?: LegendLayout; + title?: string; + isTitleVisible?: boolean; } // Arguments to XY chart expression, with computed properties diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx index da0997b7988dc..ed0eaa2ce505c 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx @@ -30,6 +30,7 @@ import { VerticalAlignment, XYChartSeriesIdentifier, Tooltip, + LegendValue, } from '@elastic/charts'; import { Datatable } from '@kbn/expressions-plugin/common'; import { EmptyPlaceholder } from '@kbn/charts-plugin/public'; @@ -58,7 +59,7 @@ import { XYChart, XYChartRenderProps } from './xy_chart'; import { ExtendedDataLayerConfig, XYProps, AnnotationLayerConfigResult } from '../../common/types'; import { DataLayers } from './data_layers'; import { SplitChart } from './split_chart'; -import { LegendSize, XYLegendValue } from '@kbn/visualizations-plugin/common'; +import { LegendSize } from '@kbn/visualizations-plugin/common'; import type { LayerCellValueActions } from '../types'; const onClickValue = jest.fn(); @@ -744,7 +745,7 @@ describe('XYChart component', () => { {...defaultProps} args={{ ...args, - legend: { ...args.legend, legendStats: [XYLegendValue.CurrentAndLastValue] }, + legend: { ...args.legend, legendStats: [LegendValue.CurrentAndLastValue] }, }} /> ); @@ -760,14 +761,14 @@ describe('XYChart component', () => { ...args, legend: { ...args.legend, - legendStats: [XYLegendValue.CurrentAndLastValue], + legendStats: [LegendValue.CurrentAndLastValue], }, layers: [dateHistogramLayer], }} /> ); expect(component.find(Settings).at(0).prop('legendValues')).toEqual([ - XYLegendValue.CurrentAndLastValue, + LegendValue.CurrentAndLastValue, ]); }); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 58a02a1bf3215..6479abbdd42d0 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -828,6 +828,8 @@ export function XYChart({ showLegend={showLegend} legendPosition={legend?.isInside ? legendInsideParams : legend.position} legendSize={LegendSizeToPixels[legend.legendSize ?? DEFAULT_LEGEND_SIZE]} + legendValues={isHistogramViz ? legend.legendStats : []} + legendTitle={getLegendTitle(legend.title, dataLayers[0], legend.isTitleVisible)} theme={[ { barSeriesStyle: { @@ -877,7 +879,6 @@ export function XYChart({ ) : undefined } - legendValues={isHistogramViz ? legend.legendStats : []} ariaLabel={args.ariaLabel} ariaUseDefaultSummary={!args.ariaLabel} orderOrdinalBinsBy={ @@ -1038,3 +1039,23 @@ export function XYChart({
); } + +const defaultLegendTitle = i18n.translate('expressionXY.xyChart.legendTitle', { + defaultMessage: 'Legend', +}); + +function getLegendTitle( + title: string | undefined, + layer?: CommonXYDataLayerConfig, + isTitleVisible?: boolean +) { + if (!isTitleVisible) { + return undefined; + } + if (typeof title === 'string' && title.length > 0) { + return title; + } + return layer?.splitAccessors?.[0] + ? getColumnByAccessor(layer.splitAccessors?.[0], layer?.table.columns)?.name + : defaultLegendTitle; +} diff --git a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts index d1da337a87862..5d7074ce44022 100644 --- a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts +++ b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; +import { LegendValue } from '@elastic/charts'; import { getConfiguration } from '.'; import { samplePieVis } from '../../sample_vis.test.mocks'; @@ -39,7 +39,7 @@ describe('getConfiguration', () => { percentDecimals: 2, primaryGroups: ['bucket-1'], secondaryGroups: [], - legendStats: [PartitionLegendValue.Value], + legendStats: [LegendValue.Value], truncateLegend: true, }, ], diff --git a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts index acad50d7f3d30..dc542e9e42ff4 100644 --- a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { LegendValue } from '@elastic/charts'; import { LegendDisplay, PartitionVisParams } from '@kbn/expression-partition-vis-plugin/common'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { CategoryDisplayTypes, NumberDisplayTypes, @@ -28,7 +28,7 @@ const getLayers = ( const showValuesInLegend = vis.params.labels.values ?? (vis.params.legendStats - ? vis.params.legendStats?.[0] === PartitionLegendValue.Value + ? vis.params.legendStats?.[0] === LegendValue.Value : vis.type.visConfig.defaults.showValuesInLegend); return [ @@ -50,7 +50,7 @@ const getLayers = ( vis.params.legendDisplay ?? vis.type.visConfig.defaults.legendDisplay, legendPosition: vis.params.legendPosition ?? vis.type.visConfig.defaults.legendPosition, - legendStats: showValuesInLegend ? [PartitionLegendValue.Value] : undefined, + legendStats: showValuesInLegend ? [LegendValue.Value] : undefined, nestedLegend: vis.params.nestedLegend ?? vis.type.visConfig.defaults.nestedLegend, percentDecimals: vis.params.labels.percentDecimals ?? vis.type.visConfig.defaults.labels.percentDecimals, diff --git a/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts index bc1bd87140654..88b60ba49a55f 100644 --- a/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Position, ScaleType as ECScaleType } from '@elastic/charts'; +import { LegendValue, Position, ScaleType as ECScaleType } from '@elastic/charts'; import { SeriesTypes, Column, @@ -15,7 +15,6 @@ import { XYReferenceLineLayerConfig, } from '@kbn/visualizations-plugin/common/convert_to_lens'; import { Vis } from '@kbn/visualizations-plugin/public'; -import { XYLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { Layer } from '..'; import { ChartType } from '../../../common'; import { @@ -237,7 +236,7 @@ export const getConfiguration = ( maxLines: vis.params.maxLegendLines ?? vis.type.visConfig.defaults.maxLegendLines, showSingleSeries: true, legendStats: Boolean(vis.params.labels.show ?? vis.type.visConfig.defaults.labels?.show) - ? [XYLegendValue.CurrentAndLastValue] + ? [LegendValue.CurrentAndLastValue] : undefined, }, fittingFunction: fittingFunction diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index c855aae1865dd..0a6694f1d5a8e 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -7,7 +7,7 @@ */ import moment from 'moment'; -import { Position, ScaleType as ECScaleType } from '@elastic/charts'; +import { LegendValue, Position, ScaleType as ECScaleType } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { VisToExpressionAst, @@ -20,7 +20,6 @@ import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugi import { BUCKET_TYPES } from '@kbn/data-plugin/public'; import type { TimeRangeBounds } from '@kbn/data-plugin/common'; import type { PaletteOutput } from '@kbn/charts-plugin/common/expressions/palette/types'; -import { XYLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { Dimensions, Dimension, @@ -48,7 +47,7 @@ const prepareLengend = (params: VisParams, legendSize?: LegendSize) => { shouldTruncate: params.truncateLegend, showSingleSeries: true, legendSize, - legendStats: params.labels.show ? [XYLegendValue.CurrentAndLastValue] : undefined, + legendStats: params.labels.show ? [LegendValue.CurrentAndLastValue] : undefined, }); return buildExpression([legend]); diff --git a/src/plugins/visualizations/common/constants.ts b/src/plugins/visualizations/common/constants.ts index f8f6409b71122..4ae3e174fc5c6 100644 --- a/src/plugins/visualizations/common/constants.ts +++ b/src/plugins/visualizations/common/constants.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { LegendValue } from '@elastic/charts'; import { METRIC_TYPES, BUCKET_TYPES } from '@kbn/data-plugin/common'; export const SAVED_OBJECTS_LIMIT_SETTING = 'savedObjects:listingLimit'; @@ -37,6 +38,11 @@ export enum LegendSize { EXTRA_LARGE = 'xlarge', } +export enum LegendLayout { + Table = 'table', + List = 'list', +} + export const LegendSizeToPixels = { [LegendSize.AUTO]: undefined, [LegendSize.SMALL]: 80, @@ -52,10 +58,25 @@ export const SUPPORTED_AGGREGATIONS = [ ...Object.values(BUCKET_TYPES), ] as const; -export enum XYLegendValue { - CurrentAndLastValue = 'currentAndLastValue', -} +export type XYLegendValue = Extract< + LegendValue, + | 'currentAndLastValue' + | 'lastValue' + | 'lastNonNullValue' + | 'average' + | 'median' + | 'max' + | 'min' + | 'firstValue' + | 'firstNonNullValue' + | 'total' + | 'count' + | 'distinctCount' + | 'variance' + | 'stdDeviation' + | 'range' + | 'difference' + | 'differencePercent' +>; -export enum PartitionLegendValue { - Value = 'value', -} +export type PartitionLegendValue = Extract; diff --git a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts index 675355dc69315..d167935720cf4 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -10,7 +10,7 @@ import { HorizontalAlignment, LayoutDirection, Position, VerticalAlignment } fro import { $Values } from '@kbn/utility-types'; import type { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; import { KibanaQueryOutput } from '@kbn/data-plugin/common'; -import { LegendSize, XYLegendValue, PartitionLegendValue } from '../../constants'; +import { LegendSize, type XYLegendValue, type PartitionLegendValue } from '../../constants'; import { CategoryDisplayTypes, PartitionChartTypes, diff --git a/src/plugins/visualizations/common/index.ts b/src/plugins/visualizations/common/index.ts index f5047212603c1..82dfd8d76b29a 100644 --- a/src/plugins/visualizations/common/index.ts +++ b/src/plugins/visualizations/common/index.ts @@ -20,6 +20,7 @@ export { LegendSize, LegendSizeToPixels, DEFAULT_LEGEND_SIZE, - XYLegendValue, - PartitionLegendValue, + LegendLayout, + type XYLegendValue, + type PartitionLegendValue, } from './constants'; diff --git a/x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.tsx b/x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.tsx deleted file mode 100644 index a65425d07d7a0..0000000000000 --- a/x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.tsx +++ /dev/null @@ -1,101 +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 React, { useCallback, useMemo } from 'react'; -import { EuiSpacer, EuiFormRow } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useDebouncedValue } from '@kbn/visualization-ui-components'; -import type { AxesSettingsConfig } from '../../../visualizations/xy/types'; -import { type LabelMode, VisLabel } from '../..'; - -type AxesSettingsConfigKeys = keyof AxesSettingsConfig; - -export interface AxisTitleSettingsProps { - /** - * Determines the axis - */ - axis: AxesSettingsConfigKeys; - /** - * Determines the axis title - */ - axisTitle: string | undefined; - /** - * Callback to axis title change for both title and visibility - */ - updateTitleState: ( - state: { title?: string; visible: boolean }, - axis: AxesSettingsConfigKeys - ) => void; - /** - * Determines if the title visibility switch is on and the input text is disabled - */ - isAxisTitleVisible: boolean; -} - -export const AxisTitleSettings: React.FunctionComponent = ({ - axis, - axisTitle, - updateTitleState, - isAxisTitleVisible, -}) => { - const axisState = useMemo( - () => ({ - title: axisTitle, - visibility: - !axisTitle && isAxisTitleVisible - ? 'auto' - : isAxisTitleVisible - ? 'custom' - : ('none' as LabelMode), - }), - [axisTitle, isAxisTitleVisible] - ); - const onTitleChange = useCallback( - ({ title, visibility }: { title?: string; visibility: LabelMode }) => - updateTitleState({ title, visible: visibility !== 'none' }, axis), - [axis, updateTitleState] - ); - const { inputValue: localAxisState, handleInputChange: onLocalTitleChange } = useDebouncedValue<{ - title?: string; - visibility: LabelMode; - }>( - { - value: axisState, - onChange: onTitleChange, - }, - { allowFalsyValue: true } - ); - - return ( - <> - - { - onLocalTitleChange({ title: label, visibility: mode }); - }} - /> - - - - ); -}; diff --git a/x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.test.tsx b/x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.test.tsx similarity index 80% rename from x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.test.tsx rename to x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.test.tsx index 7783ce163830a..807e02ff05641 100644 --- a/x-pack/plugins/lens/public/shared_components/axis/title/axis_title_settings.test.tsx +++ b/x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.test.tsx @@ -6,16 +6,16 @@ */ import React from 'react'; -import { AxisTitleSettings, AxisTitleSettingsProps } from './axis_title_settings'; +import { ToolbarTitleSettings, TitleSettingsProps } from './toolbar_title_settings'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -const renderAxisTicksSettings = (propsOverrides?: Partial) => { +const renderAxisTicksSettings = (propsOverrides?: Partial) => { const rtlRender = render( - @@ -35,33 +35,33 @@ describe('Axes Title settings', () => { }); it('should set the mode to Auto if no title is passed over', () => { - const { getAxisTitleInput } = renderAxisTicksSettings({ axisTitle: undefined }); + const { getAxisTitleInput } = renderAxisTicksSettings({ title: undefined }); expect(getAxisTitleInput()).toHaveValue(''); }); it('should set the mode to Auto if empty title is passed over', () => { - const { getAxisTitleInput } = renderAxisTicksSettings({ axisTitle: '' }); + const { getAxisTitleInput } = renderAxisTicksSettings({ title: '' }); expect(getAxisTitleInput()).toHaveValue(''); }); it('should set the mode to None if empty title is passed over and the visibility is set to false', () => { const { getAxisTitleSelect } = renderAxisTicksSettings({ - axisTitle: '', - isAxisTitleVisible: false, + title: '', + isTitleVisible: false, }); expect(getAxisTitleSelect()).toHaveValue('none'); }); it('should disable the input text if the switch is off', () => { const { getAxisTitleInput } = renderAxisTicksSettings({ - isAxisTitleVisible: false, + isTitleVisible: false, }); expect(getAxisTitleInput()).toBeDisabled(); }); it('should allow custom mode on user input even with empty string', () => { const { getAxisTitleSelect, getAxisTitleInput } = renderAxisTicksSettings({ - axisTitle: '', + title: '', }); userEvent.selectOptions(getAxisTitleSelect(), 'custom'); expect(getAxisTitleSelect()).toHaveValue('custom'); @@ -71,8 +71,8 @@ describe('Axes Title settings', () => { it('should reset the label when moving from custom to auto', async () => { const updateTitleStateSpy = jest.fn(); const { getAxisTitleSelect, getAxisTitleInput } = renderAxisTicksSettings({ - isAxisTitleVisible: true, - axisTitle: 'Custom title', + isTitleVisible: true, + title: 'Custom title', updateTitleState: updateTitleStateSpy, }); userEvent.selectOptions(getAxisTitleSelect(), 'auto'); diff --git a/x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.tsx b/x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.tsx new file mode 100644 index 0000000000000..258e41624402d --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/axis/title/toolbar_title_settings.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; +import { EuiSpacer, EuiFormRow } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useDebouncedValue } from '@kbn/visualization-ui-components'; +import type { AxesSettingsConfig } from '../../../visualizations/xy/types'; +import { type LabelMode, VisLabel } from '../..'; + +type SettingsConfigKeys = keyof AxesSettingsConfig | 'legend'; + +export interface TitleSettingsProps { + /** + * Determines the settingId - either axis or legend + */ + settingId: SettingsConfigKeys; + /** + * Determines the title + */ + title: string | undefined; + /** + * Callback to title change for both title and visibility + */ + updateTitleState: ( + state: { title?: string; visible: boolean }, + settingId: SettingsConfigKeys + ) => void; + /** + * Determines if the title visibility switch is on and the input text is disabled + */ + isTitleVisible: boolean; + strings?: { + header: string; + label: string; + getDataTestSubj: (axis: SettingsConfigKeys) => string; + }; + placeholder?: string; +} + +const axisStrings = { + header: i18n.translate('xpack.lens.label.shared.axisHeader', { + defaultMessage: 'Axis title', + }), + label: i18n.translate('xpack.lens.shared.axisNameLabel', { + defaultMessage: 'Axis title', + }), + getDataTestSubj: (axis: SettingsConfigKeys) => `lns${axis}AxisTitle`, +}; + +export const ToolbarTitleSettings: React.FunctionComponent = ({ + settingId, + title, + updateTitleState, + isTitleVisible, + strings = axisStrings, + placeholder = i18n.translate('xpack.lens.shared.overwriteAxisTitle', { + defaultMessage: 'Overwrite axis title', + }), +}) => { + const axisState = useMemo( + () => ({ + title, + visibility: + !title && isTitleVisible ? 'auto' : isTitleVisible ? 'custom' : ('none' as LabelMode), + }), + [title, isTitleVisible] + ); + const onTitleChange = useCallback( + ({ title: t, visibility }: { title?: string; visibility: LabelMode }) => + updateTitleState({ title: t, visible: visibility !== 'none' }, settingId), + [settingId, updateTitleState] + ); + const { inputValue: localState, handleInputChange: onLocalTitleChange } = useDebouncedValue<{ + title?: string; + visibility: LabelMode; + }>( + { + value: axisState, + onChange: onTitleChange, + }, + { allowFalsyValue: true } + ); + + return ( + <> + + { + onLocalTitleChange({ title: label, visibility: mode }); + }} + /> + + + + ); +}; diff --git a/x-pack/plugins/lens/public/shared_components/index.ts b/x-pack/plugins/lens/public/shared_components/index.ts index cd663ca08601e..1e3f84dd2accb 100644 --- a/x-pack/plugins/lens/public/shared_components/index.ts +++ b/x-pack/plugins/lens/public/shared_components/index.ts @@ -22,7 +22,7 @@ export { export * from './coloring'; export * from './helpers'; export { ValueLabelsSettings } from './value_labels_settings'; -export { AxisTitleSettings } from './axis/title/axis_title_settings'; +export { ToolbarTitleSettings } from './axis/title/toolbar_title_settings'; export { AxisTicksSettings } from './axis/ticks/axis_ticks_settings'; export * from './static_header'; export * from './vis_label'; diff --git a/x-pack/plugins/lens/public/shared_components/legend/layout/columns_number_setting.tsx b/x-pack/plugins/lens/public/shared_components/legend/layout/columns_number_setting.tsx index 1f21c9004043e..81d1acd84e0fe 100644 --- a/x-pack/plugins/lens/public/shared_components/legend/layout/columns_number_setting.tsx +++ b/x-pack/plugins/lens/public/shared_components/legend/layout/columns_number_setting.tsx @@ -22,22 +22,22 @@ interface ColumnsNumberSettingProps { */ onFloatingColumnsChange?: (value: number) => void; /** - * Indicates if legend is located outside + * Indicates if the component should be hidden */ - isLegendOutside: boolean; + isHidden: boolean; } export const ColumnsNumberSetting = ({ floatingColumns, onFloatingColumnsChange = () => {}, - isLegendOutside, + isHidden, }: ColumnsNumberSettingProps) => { const { inputValue, handleInputChange } = useDebouncedValue({ value: floatingColumns ?? DEFAULT_FLOATING_COLUMNS, onChange: onFloatingColumnsChange, }); - if (isLegendOutside) return null; + if (isHidden) return null; return ( { let defaultProps: LegendSettingsPopoverProps; @@ -49,7 +50,6 @@ describe('Legend Settings', () => { renderOptions ); const openLegendPopover = () => userEvent.click(screen.getByRole('button', { name: 'Legend' })); - openLegendPopover(); return { @@ -125,4 +125,28 @@ describe('Legend Settings', () => { renderLegendSettingsPopover({ mode: 'hide', renderNestedLegendSwitch: true }); expect(screen.queryByRole('switch', { name: 'Nested' })).toBeNull(); }); + + it('should display allowed legend stats', () => { + const onLegendStatsChange = jest.fn(); + renderLegendSettingsPopover({ + allowedLegendStats: [ + { + label: 'Current and last value', + value: LegendValue.CurrentAndLastValue, + toolTipContent: 'Shows the current and last value', + }, + { + label: 'Average', + value: LegendValue.Average, + toolTipContent: 'Shows the average value', + }, + ], + onLegendStatsChange, + }); + expect(screen.queryByRole('button', { name: 'Layout' })).toBeNull(); + fireEvent.click(screen.getByRole('combobox', { name: 'Statistics' })); + fireEvent.click(screen.getByRole('option', { name: 'Current and last value' })); + // expect(screen.getByRole('group', { name: 'Layout' })).toBeInTheDocument(); + expect(onLegendStatsChange).toBeCalledWith([LegendValue.CurrentAndLastValue], false); + }); }); diff --git a/x-pack/plugins/lens/public/shared_components/legend/legend_settings_popover.tsx b/x-pack/plugins/lens/public/shared_components/legend/legend_settings_popover.tsx index ccfdaa29089b1..80389e041763f 100644 --- a/x-pack/plugins/lens/public/shared_components/legend/legend_settings_popover.tsx +++ b/x-pack/plugins/lens/public/shared_components/legend/legend_settings_popover.tsx @@ -15,8 +15,10 @@ import { EuiFieldNumber, EuiFlexItem, EuiFlexGroup, + EuiComboBox, + EuiHorizontalRule, } from '@elastic/eui'; -import { Position, VerticalAlignment, HorizontalAlignment } from '@elastic/charts'; +import { Position, VerticalAlignment, HorizontalAlignment, LegendValue } from '@elastic/charts'; import { LegendSize } from '@kbn/visualizations-plugin/public'; import { useDebouncedValue } from '@kbn/visualization-ui-components'; import { XYLegendValue } from '@kbn/visualizations-plugin/common/constants'; @@ -24,8 +26,10 @@ import { ToolbarPopover, type ToolbarPopoverProps } from '../toolbar_popover'; import { LegendLocationSettings } from './location/legend_location_settings'; import { ColumnsNumberSetting } from './layout/columns_number_setting'; import { LegendSizeSettings } from './size/legend_size_settings'; +import { nonNullable } from '../../utils'; +import { ToolbarTitleSettings } from '../axis/title/toolbar_title_settings'; -export interface LegendSettingsPopoverProps { +export interface LegendSettingsPopoverProps { /** * Determines the legend display options */ @@ -107,17 +111,18 @@ export interface LegendSettingsPopoverProps { */ onNestedLegendChange?: (event: EuiSwitchEvent) => void; /** - * value in legend status + * current value in legend stats */ - legendStats?: S[]; + legendStats?: LegendStats[]; /** - * Callback on value in legend status change + * legend statistics that are allowed */ - onLegendStatsChange?: (checked?: boolean) => void; + allowedLegendStats?: Array<{ label: string; value: LegendStats; toolTipContent?: string }>; /** - * If true, value in legend switch is rendered + * Callback on value in legend stats change */ - allowLegendStats?: boolean; + onLegendStatsChange?: (legendStats?: LegendStats[], hasConvertedToTable?: boolean) => void; + /** * Button group position */ @@ -135,6 +140,10 @@ export interface LegendSettingsPopoverProps { * (We're trying to get people to stop using it so it can eventually be removed.) */ showAutoLegendSizeOption: boolean; + titlePlaceholder?: string; + legendTitle?: string; + isTitleVisible?: boolean; + onLegendTitleChange?: (state: { title?: string; visible: boolean }) => void; } const DEFAULT_TRUNCATE_LINES = 1; @@ -182,9 +191,30 @@ const PANEL_STYLE = { width: '500px', }; -export function LegendSettingsPopover({ +const legendTitleStrings = { + header: i18n.translate('xpack.lens.label.shared.legendHeader', { + defaultMessage: 'Series header', + }), + label: i18n.translate('xpack.lens.shared.Lagend ', { + defaultMessage: 'Series header', + }), + placeholder: i18n.translate('xpack.lens.shared.overwriteLegendTitle', { + defaultMessage: 'Overwrite series header', + }), + getDataTestSubj: () => `lnsLegendTableSeriesHeader`, +}; + +export function shouldDisplayTable(legendValues: LegendValue[]) { + return legendValues.some((v) => v !== LegendValue.CurrentAndLastValue); +} + +export function LegendSettingsPopover({ + allowedLegendStats = [], legendOptions, mode, + legendTitle, + isTitleVisible, + onLegendTitleChange, onDisplayChange, position, location, @@ -198,9 +228,8 @@ export function LegendSettingsPopover({ renderNestedLegendSwitch, nestedLegend, onNestedLegendChange = noop, - legendStats, + legendStats = [], onLegendStatsChange = noop, - allowLegendStats, groupPosition = 'right', maxLines, onMaxLinesChange = noop, @@ -209,7 +238,20 @@ export function LegendSettingsPopover({ legendSize, onLegendSizeChange, showAutoLegendSizeOption, -}: LegendSettingsPopoverProps) { + titlePlaceholder, +}: LegendSettingsPopoverProps) { + const isLegendNotHidden = mode !== 'hide'; + + const showsStatisticsSetting = isLegendNotHidden && allowedLegendStats.length > 1; + + const showsShowValueSetting = + isLegendNotHidden && + allowedLegendStats.length === 1 && + (allowedLegendStats[0].value === LegendValue.CurrentAndLastValue || + allowedLegendStats[0].value === LegendValue.Value); + + const showsLegendTitleSetting = shouldDisplayTable(legendStats) && !!onLegendTitleChange; + return ( ({ ({ onChange={onDisplayChange} /> - {mode !== 'hide' && ( + + {isLegendNotHidden && ( <> ({ )} + + )} + {showsStatisticsSetting && ( + <> + - - - - - - - - + allowedLegendStats.find((option) => option.value === value)) + .filter(nonNullable)} + onChange={(options) => { + const newLegendStats = options.map(({ value }) => value).filter(nonNullable); + const hasConvertedToTable = + !shouldDisplayTable(legendStats) && shouldDisplayTable(newLegendStats); + onLegendStatsChange(newLegendStats, hasConvertedToTable); + }} + isClearable={true} + compressed + /> + + )} - {renderNestedLegendSwitch && ( - + {showsLegendTitleSetting && ( + + )} + {showsShowValueSetting && ( + + { + onLegendStatsChange(ev.target.checked ? [allowedLegendStats[0].value] : []); + }} + /> + + )} + + {isLegendNotHidden && ( + + + - - )} - {allowLegendStats && ( - - { - onLegendStatsChange(ev.target.checked); - }} + + + - - )} - + +
+ + )} + + {isLegendNotHidden && renderNestedLegendSwitch && ( + + + )} ); diff --git a/x-pack/plugins/lens/public/shared_components/legend/location/legend_location_settings.tsx b/x-pack/plugins/lens/public/shared_components/legend/location/legend_location_settings.tsx index 039f778d7439e..5c28b2e2a0888 100644 --- a/x-pack/plugins/lens/public/shared_components/legend/location/legend_location_settings.tsx +++ b/x-pack/plugins/lens/public/shared_components/legend/location/legend_location_settings.tsx @@ -158,7 +158,7 @@ export const LegendLocationSettings: React.FunctionComponent @@ -167,7 +167,7 @@ export const LegendLocationSettings: React.FunctionComponent diff --git a/x-pack/plugins/lens/public/shared_components/vis_label.tsx b/x-pack/plugins/lens/public/shared_components/vis_label.tsx index 6d54d1633d439..10c8f3ea42ed6 100644 --- a/x-pack/plugins/lens/public/shared_components/vis_label.tsx +++ b/x-pack/plugins/lens/public/shared_components/vis_label.tsx @@ -76,10 +76,9 @@ export function VisLabel({ data-test-subj={`${dataTestSubj}-select`} aria-label="Label" onChange={({ target }) => { - const title = - target.value === 'custom' ? '' : target.value === 'auto' ? undefined : label; handleChange({ - label: title, + // reset title to undefined when switching mode + label: undefined, mode: target.value as LabelMode, }); }} diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/toolbar_component.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/toolbar_component.tsx index c621a59e9ea9b..327bdef6c5bc4 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/toolbar_component.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/toolbar_component.tsx @@ -17,7 +17,7 @@ import { LegendSettingsPopover, ToolbarPopover, ValueLabelsSettings, - AxisTitleSettings, + ToolbarTitleSettings, AxisTicksSettings, } from '../../shared_components'; import type { HeatmapVisualizationState } from './types'; @@ -151,9 +151,9 @@ export const HeatmapToolbar = memo( buttonDataTestSubj="lnsHeatmapVerticalAxisButton" panelClassName="lnsVisToolbarAxis__popover" > - { setState({ ...state, @@ -164,7 +164,7 @@ export const HeatmapToolbar = memo( }, }); }} - isAxisTitleVisible={state?.gridConfig.isYAxisTitleVisible} + isTitleVisible={state?.gridConfig.isYAxisTitleVisible} /> - setState({ ...state, @@ -210,7 +210,7 @@ export const HeatmapToolbar = memo( }, }) } - isAxisTitleVisible={state?.gridConfig.isXAxisTitleVisible} + isTitleVisible={state?.gridConfig.isXAxisTitleVisible} /> = { }, legend: { flat: true, - defaultLegendStats: [PartitionLegendValue.Value], + defaultLegendStats: [LegendValue.Value], hideNestedLegendSwitch: true, getShowLegendDefault: () => true, }, diff --git a/x-pack/plugins/lens/public/visualizations/partition/persistence.tsx b/x-pack/plugins/lens/public/visualizations/partition/persistence.tsx index 9fc04b3702296..ba8632659836a 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/persistence.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/persistence.tsx @@ -5,8 +5,8 @@ * 2.0. */ +import { LegendValue } from '@elastic/charts'; import { cloneDeep } from 'lodash'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { PieLayerState, PieVisualizationState } from '../../../common/types'; type PersistedPieLayerState = PieLayerState & { @@ -28,7 +28,7 @@ function convertToLegendStats(state: PieVisualizationState) { if ('showValuesInLegend' in l) { l.legendStats = [ ...new Set([ - ...(l.showValuesInLegend ? [PartitionLegendValue.Value] : []), + ...(l.showValuesInLegend ? [LegendValue.Value] : []), ...(l.legendStats || []), ]), ]; diff --git a/x-pack/plugins/lens/public/visualizations/partition/render_helpers.test.ts b/x-pack/plugins/lens/public/visualizations/partition/render_helpers.test.ts index e273fde23f4db..bef4db9d0a2f6 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/render_helpers.test.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/render_helpers.test.ts @@ -10,7 +10,7 @@ import type { Datatable } from '@kbn/expressions-plugin/public'; import { checkTableForContainsSmallValues, getLegendStats } from './render_helpers'; import { PieLayerState } from '../../../common/types'; import { PieChartTypes } from '../../../common/constants'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; +import { LegendValue } from '@elastic/charts'; describe('render helpers', () => { describe('#checkTableForContainsSmallValues', () => { @@ -72,28 +72,22 @@ describe('render helpers', () => { describe('#getLegendStats', () => { it('should firstly read the state value', () => { expect( - getLegendStats( - { legendStats: [PartitionLegendValue.Value] } as PieLayerState, - PieChartTypes.WAFFLE - ) - ).toEqual([PartitionLegendValue.Value]); + getLegendStats({ legendStats: [LegendValue.Value] } as PieLayerState, PieChartTypes.WAFFLE) + ).toEqual([LegendValue.Value]); expect( - getLegendStats( - { legendStats: [] as PartitionLegendValue[] } as PieLayerState, - PieChartTypes.WAFFLE - ) + getLegendStats({ legendStats: [] as LegendValue[] } as PieLayerState, PieChartTypes.WAFFLE) ).toEqual([]); }); it('should read value from meta in case of value in state is undefined', () => { expect(getLegendStats({} as PieLayerState, PieChartTypes.WAFFLE)).toEqual([ - PartitionLegendValue.Value, + LegendValue.Value, ]); expect( getLegendStats({ legendStats: undefined } as PieLayerState, PieChartTypes.WAFFLE) - ).toEqual([PartitionLegendValue.Value]); + ).toEqual([LegendValue.Value]); expect(getLegendStats({} as PieLayerState, PieChartTypes.PIE)).toEqual(undefined); }); diff --git a/x-pack/plugins/lens/public/visualizations/partition/render_helpers.ts b/x-pack/plugins/lens/public/visualizations/partition/render_helpers.ts index 869597f92dcb1..b2bd2cdd9a058 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/render_helpers.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/render_helpers.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { LegendValue } from '@elastic/charts'; import type { Datatable } from '@kbn/expressions-plugin/public'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; import type { PieChartType, PieLayerState } from '../../../common/types'; import { PartitionChartsMeta } from './partition_charts_meta'; @@ -14,7 +14,7 @@ export const getLegendStats = (layer: PieLayerState, shape: PieChartType) => { if ('defaultLegendStats' in PartitionChartsMeta[shape]?.legend) { return ( layer.legendStats ?? - PartitionChartsMeta[shape].legend.defaultLegendStats ?? [PartitionLegendValue.Value] + PartitionChartsMeta[shape].legend.defaultLegendStats ?? [LegendValue.Value] ); } }; diff --git a/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx b/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx index 792e45ba99b2b..dfccdccc9f85f 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx @@ -16,10 +16,10 @@ import { EuiHorizontalRule, EuiButtonGroup, } from '@elastic/eui'; -import type { Position } from '@elastic/charts'; +import { LegendValue, Position } from '@elastic/charts'; import { LegendSize } from '@kbn/visualizations-plugin/public'; import { useDebouncedValue } from '@kbn/visualization-ui-components'; -import { PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; +import { type PartitionLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { DEFAULT_PERCENT_DECIMALS } from './constants'; import { PartitionChartsMeta } from './partition_charts_meta'; import { PieVisualizationState, SharedPieLayerState } from '../../../common/types'; @@ -29,6 +29,15 @@ import { ToolbarPopover, LegendSettingsPopover } from '../../shared_components'; import { getDefaultVisualValuesForLayer } from '../../shared_components/datasource_default_values'; import { getLegendStats } from './render_helpers'; +const partitionLegendValues = [ + { + value: LegendValue.Value, + label: i18n.translate('xpack.lens.shared.legendValues.value', { + defaultMessage: 'Value', + }), + }, +]; + const legendOptions: Array<{ value: SharedPieLayerState['legendDisplay']; label: string; @@ -135,10 +144,8 @@ export function PieToolbar(props: VisualizationToolbarProps { - onStateChange({ - legendStats: checked ? [PartitionLegendValue.Value] : [], - }); + (legendStats) => { + onStateChange({ legendStats }); }, [onStateChange] ); @@ -250,7 +257,11 @@ export function PieToolbar(props: VisualizationToolbarProps { describe('converting to legendStats', () => { it('loads a chart with `legendStats` property', () => { const persistedState = getExampleState(); - persistedState.layers[0].legendStats = [PartitionLegendValue.Value]; + persistedState.layers[0].legendStats = [LegendValue.Value]; const runtimeState = pieVisualization.initialize(() => 'first', persistedState); diff --git a/x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.test.ts b/x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.test.ts new file mode 100644 index 0000000000000..16bc56cf983a9 --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.test.ts @@ -0,0 +1,113 @@ +/* + * Copyright 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 { LegendValue } from '@elastic/charts'; +import { getLegendStatsTelemetryEvents } from './legend_stats_telemetry_helpers'; + +describe('legend_stats_telemetry_helpers', () => { + it('no events if legend stats are not defined', () => { + expect(getLegendStatsTelemetryEvents(undefined)).toEqual([]); + }); + it('ignores single CurrentAndLastValue stat as it does not trigger table view', () => { + expect(getLegendStatsTelemetryEvents([LegendValue.CurrentAndLastValue])).toEqual([]); + expect( + getLegendStatsTelemetryEvents([LegendValue.CurrentAndLastValue, LegendValue.Average]) + ).toEqual([ + 'lens_legend_stats', + 'lens_legend_stats_currentAndLastValue', + 'lens_legend_stats_average', + 'lens_legend_stats_amount_2', + ]); + }); + + it('no events if no changes made in color mapping', () => { + expect(getLegendStatsTelemetryEvents([LegendValue.Average], [LegendValue.Average])).toEqual([]); + expect( + getLegendStatsTelemetryEvents( + [LegendValue.CurrentAndLastValue, LegendValue.Average], + [LegendValue.CurrentAndLastValue, LegendValue.Average] + ) + ).toEqual([]); + }); + describe('calculates counter events properly', () => { + it('returns single count event', () => { + expect(getLegendStatsTelemetryEvents([LegendValue.Average])).toEqual([ + 'lens_legend_stats', + 'lens_legend_stats_average', + 'lens_legend_stats_amount_1', + ]); + }); + it('returns 2 count event', () => { + expect(getLegendStatsTelemetryEvents([LegendValue.Average, LegendValue.Count])).toEqual([ + 'lens_legend_stats', + 'lens_legend_stats_average', + 'lens_legend_stats_count', + 'lens_legend_stats_amount_2', + ]); + }); + it('returns 3 count event', () => { + expect( + getLegendStatsTelemetryEvents([ + LegendValue.Average, + LegendValue.Count, + LegendValue.CurrentAndLastValue, + ]) + ).toEqual([ + 'lens_legend_stats', + 'lens_legend_stats_average', + 'lens_legend_stats_count', + 'lens_legend_stats_currentAndLastValue', + 'lens_legend_stats_amount_3', + ]); + }); + it('returns 4 count event', () => { + expect( + getLegendStatsTelemetryEvents([ + LegendValue.CurrentAndLastValue, + LegendValue.Max, + LegendValue.Min, + LegendValue.Average, + ]) + ).toEqual([ + 'lens_legend_stats', + 'lens_legend_stats_currentAndLastValue', + 'lens_legend_stats_max', + 'lens_legend_stats_min', + 'lens_legend_stats_average', + 'lens_legend_stats_amount_4_to_7', + ]); + }); + + it('returns >8 count event', () => { + expect( + getLegendStatsTelemetryEvents([ + LegendValue.CurrentAndLastValue, + LegendValue.Max, + LegendValue.Min, + LegendValue.Average, + LegendValue.Count, + LegendValue.Total, + LegendValue.LastValue, + LegendValue.FirstValue, + LegendValue.Median, + ]) + ).toEqual([ + 'lens_legend_stats', + 'lens_legend_stats_currentAndLastValue', + 'lens_legend_stats_max', + 'lens_legend_stats_min', + 'lens_legend_stats_average', + 'lens_legend_stats_count', + 'lens_legend_stats_total', + 'lens_legend_stats_lastValue', + 'lens_legend_stats_firstValue', + 'lens_legend_stats_median', + 'lens_legend_stats_amount_above_8', + ]); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.ts b/x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.ts new file mode 100644 index 0000000000000..87143688c206d --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/legend_stats_telemetry_helpers.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isEqual } from 'lodash'; +import { XYLegendValue } from '@kbn/visualizations-plugin/common'; +import { nonNullable } from '../../utils'; +import { shouldDisplayTable } from '../../shared_components/legend/legend_settings_popover'; + +const LEGEND_STATS_PREFIX = 'lens_legend_stats'; +const constructName = (eventName: string) => `${LEGEND_STATS_PREFIX}${eventName}`; + +export const getLegendStatsTelemetryEvents = ( + legendStats: XYLegendValue[] | undefined, + prevLegendStats?: XYLegendValue[] | undefined +) => { + if (!legendStats || !legendStats.length || isEqual(legendStats, prevLegendStats)) { + return []; + } + if (!shouldDisplayTable(legendStats)) { + return []; + } + const mainEvent = LEGEND_STATS_PREFIX; + const typesEvents = legendStats.map((legendStat) => { + return constructName(`_${legendStat}`); + }); + const counterText = getRangeText(legendStats.length); + const counterEvent = counterText ? constructName(counterText) : undefined; + + return [mainEvent, ...typesEvents, counterEvent].filter(nonNullable); +}; + +function getRangeText(n: number) { + if (n < 1) { + return; + } + if (n < 4) { + return `_amount_${String(n)}`; + } + if (n >= 4 && n <= 7) { + return '_amount_4_to_7'; + } + if (n >= 8) { + return '_amount_above_8'; + } +} diff --git a/x-pack/plugins/lens/public/visualizations/xy/persistence.ts b/x-pack/plugins/lens/public/visualizations/xy/persistence.ts index 5191cc96bac3d..8ad5d82d364e2 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/persistence.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/persistence.ts @@ -9,8 +9,8 @@ import { v4 as uuidv4 } from 'uuid'; import type { SavedObjectReference } from '@kbn/core/public'; import { EVENT_ANNOTATION_GROUP_TYPE } from '@kbn/event-annotation-common'; import { cloneDeep } from 'lodash'; -import { XYLegendValue } from '@kbn/visualizations-plugin/common/constants'; +import { LegendValue } from '@elastic/charts'; import { layerTypes } from '../../../common/layer_types'; import { AnnotationGroups } from '../../types'; import { @@ -278,7 +278,7 @@ function convertToLegendStats(state: XYState & { valuesInLegend?: unknown }) { ...state.legend, legendStats: [ ...new Set([ - ...(valuesInLegend ? [XYLegendValue.CurrentAndLastValue] : []), + ...(valuesInLegend ? [LegendValue.CurrentAndLastValue] : []), ...(state.legend.legendStats || []), ]), ], diff --git a/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts b/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts index 76e00c892d243..c756c4eb137a9 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts @@ -293,6 +293,7 @@ export const buildXYExpression = ( : state.legend.legendSize ? state.legend.legendSize : undefined, + layout: state.legend.layout, horizontalAlignment: state.legend.horizontalAlignment && state.legend.isInside ? state.legend.horizontalAlignment @@ -309,6 +310,8 @@ export const buildXYExpression = ( : [], maxLines: state.legend.maxLines, legendStats: state.legend.legendStats, + title: state.legend.title, + isTitleVisible: state.legend.isTitleVisible, shouldTruncate: state.legend.shouldTruncate ?? getDefaultVisualValuesForLayer(state, datasourceLayers).truncateText, diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx index 73802ac2b4c47..03a391d4e29d6 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx @@ -6,7 +6,7 @@ */ import { type ExtraAppendLayerArg, getXyVisualization } from './visualization'; -import { Position } from '@elastic/charts'; +import { LegendValue, Position } from '@elastic/charts'; import { Operation, OperationDescriptor, @@ -53,7 +53,6 @@ import { } from './visualization_helpers'; import { cloneDeep } from 'lodash'; import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; -import { XYLegendValue } from '@kbn/visualizations-plugin/common/constants'; import { XYPersistedByReferenceAnnotationLayerConfig, XYPersistedByValueAnnotationLayerConfig, @@ -612,7 +611,7 @@ describe('xy_visualization', () => { ...exampleState(), legend: { ...exampleState().legend, - legendStats: [XYLegendValue.CurrentAndLastValue], + legendStats: [LegendValue.CurrentAndLastValue], }, }; diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx index 487e23e1224b7..ca99a3a7fd853 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx @@ -118,7 +118,9 @@ import { AddLayerButton } from './add_layer'; import { LayerSettings } from './layer_settings'; import { IgnoredGlobalFiltersEntries } from '../../shared_components/ignore_global_filter'; import { getColorMappingTelemetryEvents } from '../../lens_ui_telemetry/color_telemetry_helpers'; +import { getLegendStatsTelemetryEvents } from './legend_stats_telemetry_helpers'; import { XYPersistedState, convertToPersistable, convertToRuntime } from './persistence'; +import { shouldDisplayTable } from '../../shared_components/legend/legend_settings_popover'; import { ANNOTATION_MISSING_DATE_HISTOGRAM, LAYER_SETTINGS_IGNORE_GLOBAL_FILTERS, @@ -1062,10 +1064,22 @@ export const getXyVisualization = ({ getTelemetryEventsOnSave(state, prevState) { const dataLayers = getDataLayers(state.layers); const prevLayers = prevState ? getDataLayers(prevState.layers) : undefined; - return dataLayers.flatMap((l) => { + const colorMappingEvents = dataLayers.flatMap((l) => { const prevLayer = prevLayers?.find((prevL) => prevL.layerId === l.layerId); return getColorMappingTelemetryEvents(l.colorMapping, prevLayer?.colorMapping); }); + const legendStatsEvents = getLegendStatsTelemetryEvents( + state.legend.legendStats, + prevState ? prevState.legend.legendStats : undefined + ); + return colorMappingEvents.concat(legendStatsEvents); + }, + + getRenderEventCounters(state) { + if (shouldDisplayTable(state.legend.legendStats ?? [])) { + return [`legend_stats`]; + } + return []; }, }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.test.tsx index 1976b8084d7f9..fbf14216ad7a2 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.test.tsx @@ -39,7 +39,7 @@ describe('AxesSettingsPopover', () => { axis: 'x', areTickLabelsVisible: true, areGridlinesVisible: true, - isAxisTitleVisible: true, + isTitleVisible: true, toggleTickLabelsVisibility: jest.fn(), toggleGridlinesVisibility: jest.fn(), hasBarOrAreaOnAxis: false, diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx index 1714fc4a4e406..20390f322fd90 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx @@ -21,7 +21,7 @@ import { useDebouncedValue } from '@kbn/visualization-ui-components'; import { isHorizontalChart } from '../state_helpers'; import { ToolbarPopover, - AxisTitleSettings, + ToolbarTitleSettings, AxisBoundsControl, AxisTicksSettings, } from '../../../shared_components'; @@ -51,7 +51,7 @@ export interface AxisSettingsPopoverProps { */ updateTitleState: ( title: { title?: string; visible: boolean }, - axis: AxesSettingsConfigKeys + settingId: AxesSettingsConfigKeys ) => void; /** * Determines if the popover is Disabled @@ -84,7 +84,7 @@ export interface AxisSettingsPopoverProps { /** * Determines if the title visibility switch is on and the input text is disabled */ - isAxisTitleVisible: boolean; + isTitleVisible: boolean; /** * Set endzone visibility */ @@ -224,7 +224,7 @@ export const AxisSettingsPopover: React.FunctionComponent - updateTitleState(title, axis)} + isTitleVisible={isTitleVisible} /> = [ + { + value: LegendValue.Average, + label: i18n.translate('xpack.lens.shared.legendValues.average', { + defaultMessage: 'Average', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.averageDesc', { + defaultMessage: 'Average of all values in the series.', + }), + }, + { + value: LegendValue.Median, + label: i18n.translate('xpack.lens.shared.legendValues.median', { + defaultMessage: 'Median', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.medianDesc', { + defaultMessage: 'Median value in the series.', + }), + }, + { + value: LegendValue.Min, + label: i18n.translate('xpack.lens.shared.legendValues.min', { + defaultMessage: 'Minimum', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.minDesc', { + defaultMessage: 'Minimum value in the series.', + }), + }, + { + value: LegendValue.Max, + label: i18n.translate('xpack.lens.shared.legendValues.max', { + defaultMessage: 'Maximum', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.maxDesc', { + defaultMessage: 'Maximum value in the series.', + }), + }, + { + value: LegendValue.Range, + label: i18n.translate('xpack.lens.shared.legendValues.range', { + defaultMessage: 'Range', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.rangeDesc', { + defaultMessage: 'Difference between the min and the max in the series.', + }), + }, + { + value: LegendValue.LastValue, + label: i18n.translate('xpack.lens.shared.legendValues.lastValue', { + defaultMessage: 'Last value', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.lastValueDesc', { + defaultMessage: 'Last value in the series.', + }), + }, + { + value: LegendValue.LastNonNullValue, + label: i18n.translate('xpack.lens.shared.legendValues.lastNonNullValue', { + defaultMessage: 'Last non-null value', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.lastNonNullValueDesc', { + defaultMessage: 'Last non-null value in the series.', + }), + }, + { + value: LegendValue.FirstValue, + label: i18n.translate('xpack.lens.shared.legendValues.firstValue', { + defaultMessage: 'First value', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.firstValueDesc', { + defaultMessage: 'First value in the series.', + }), + }, + { + value: LegendValue.FirstNonNullValue, + label: i18n.translate('xpack.lens.shared.legendValues.firstNonNullValue', { + defaultMessage: 'First non-null value', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.firstNonNullValueDesc', { + defaultMessage: 'First non-null value in the series.', + }), + }, + { + value: LegendValue.Difference, + label: i18n.translate('xpack.lens.shared.legendValues.diff', { + defaultMessage: 'Difference', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.diffDesc', { + defaultMessage: 'Difference between first and last value in the series.', + }), + }, + { + value: LegendValue.DifferencePercent, + label: i18n.translate('xpack.lens.shared.legendValues.diffPercent', { + defaultMessage: 'Difference %', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.diffPercentDesc', { + defaultMessage: 'Difference in percent between first and last value in the series.', + }), + }, + { + value: LegendValue.Total, + label: i18n.translate('xpack.lens.shared.legendValues.total', { + defaultMessage: 'Sum', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.totalDesc', { + defaultMessage: 'The sum of all values in the series.', + }), + }, + { + value: LegendValue.Count, + label: i18n.translate('xpack.lens.shared.legendValues.count', { + defaultMessage: 'Count', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.countDesc', { + defaultMessage: 'Count of all the values in the series.', + }), + }, + { + value: LegendValue.DistinctCount, + label: i18n.translate('xpack.lens.shared.legendValues.distinctCount', { + defaultMessage: 'Distinct count', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.distinctCountDesc', { + defaultMessage: 'Count of distinct values in the series.', + }), + }, + { + value: LegendValue.Variance, + label: i18n.translate('xpack.lens.shared.legendValues.variance', { + defaultMessage: 'Variance', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.varianceDesc', { + defaultMessage: 'Variance of all the values in the series.', + }), + }, + { + value: LegendValue.StdDeviation, + label: i18n.translate('xpack.lens.shared.legendValues.stdDev', { + defaultMessage: 'Std deviation', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.stdDevDesc', { + defaultMessage: 'Standard deviation of all the values in the series.', + }), + }, + // Moved to the bottom to limit its usage. It could cause some UX issues due to the dynamic nature + // of the data displayed + { + value: LegendValue.CurrentAndLastValue, + label: i18n.translate('xpack.lens.shared.legendValues.currentValue', { + defaultMessage: 'Current or last value', + }), + toolTipContent: i18n.translate('xpack.lens.shared.legendValues.currentValueDesc', { + defaultMessage: + 'Value of the bucket being hovered or the last bucket value when not hovering.', + }), + }, +]; + +const defaultLegendTitle = i18n.translate('xpack.lens.xyChart.legendTitle', { + defaultMessage: 'Legend', +}); + export const XyToolbar = memo(function XyToolbar( props: VisualizationToolbarProps & { useLegacyTimeAxis?: boolean } ) { @@ -209,7 +375,7 @@ export const XyToolbar = memo(function XyToolbar( ); const nonOrdinalXAxis = dataLayers.every( (layer) => - !layer.xAccessor || + layer.xAccessor && getScaleType( props.frame.datasourceLayers[layer.layerId]?.getOperationForColumnId(layer.xAccessor) ?? null, @@ -336,9 +502,6 @@ export const XyToolbar = memo(function XyToolbar( ).truncateText; const legendSize = state.legend.legendSize; - - const [hadAutoLegendSize] = useState(() => legendSize === LegendSize.AUTO); - return ( @@ -362,6 +525,23 @@ export const XyToolbar = memo(function XyToolbar( }, }); }} + titlePlaceholder={ + frame.activeData?.[dataLayers[0].layerId]?.columns.find( + (col) => col.id === dataLayers[0].splitAccessor + )?.name ?? defaultLegendTitle + } + legendTitle={state?.legend.title} + onLegendTitleChange={({ title, visible }) => { + setState({ + ...state, + legend: { + ...state.legend, + title, + isTitleVisible: visible, + }, + }); + }} + isTitleVisible={state?.legend.isTitleVisible} onDisplayChange={(optionId) => { const newMode = legendOptions.find(({ id }) => id === optionId)!.value; if (newMode === 'auto') { @@ -435,14 +615,29 @@ export const XyToolbar = memo(function XyToolbar( legend: { ...state.legend, verticalAlignment, horizontalAlignment }, }); }} - allowLegendStats={nonOrdinalXAxis} + allowedLegendStats={nonOrdinalXAxis ? xyLegendValues : undefined} legendStats={state?.legend.legendStats} - onLegendStatsChange={(checked) => { + onLegendStatsChange={(legendStats, hasConvertedToTable) => { + if (hasConvertedToTable) { + setState({ + ...state, + legend: { + ...state.legend, + legendStats, + legendSize: LegendSize.AUTO, + isVisible: true, + showSingleSeries: true, + }, + }); + return; + } setState({ ...state, legend: { ...state.legend, - legendStats: checked ? [XYLegendValue.CurrentAndLastValue] : [], + legendStats, + isVisible: true, + showSingleSeries: true, }, }); }} @@ -456,7 +651,7 @@ export const XyToolbar = memo(function XyToolbar( }, }); }} - showAutoLegendSizeOption={hadAutoLegendSize} + showAutoLegendSizeOption={true} /> @@ -491,7 +686,7 @@ export const XyToolbar = memo(function XyToolbar( } orientation={labelsOrientation.yLeft} setOrientation={onLabelsOrientationChange} - isAxisTitleVisible={axisTitlesVisibilitySettings.yLeft} + isTitleVisible={axisTitlesVisibilitySettings.yLeft} extent={state?.yLeftExtent || { mode: 'full' }} setExtent={setExtentFn('yLeftExtent')} hasBarOrAreaOnAxis={hasBarOrAreaOnLeftAxis} @@ -514,7 +709,7 @@ export const XyToolbar = memo(function XyToolbar( toggleGridlinesVisibility={onGridlinesVisibilitySettingsChange} orientation={labelsOrientation.x} setOrientation={onLabelsOrientationChange} - isAxisTitleVisible={axisTitlesVisibilitySettings.x} + isTitleVisible={axisTitlesVisibilitySettings.x} endzonesVisible={!state?.hideEndzones} setEndzoneVisibility={onChangeEndzoneVisiblity} currentTimeMarkerVisible={state?.showCurrentTimeMarker} @@ -559,7 +754,7 @@ export const XyToolbar = memo(function XyToolbar( orientation={labelsOrientation.yRight} setOrientation={onLabelsOrientationChange} hasPercentageAxis={hasPercentageAxis(axisGroups, 'right', state)} - isAxisTitleVisible={axisTitlesVisibilitySettings.yRight} + isTitleVisible={axisTitlesVisibilitySettings.yRight} extent={state?.yRightExtent || { mode: 'full' }} setExtent={setExtentFn('yRightExtent')} hasBarOrAreaOnAxis={hasBarOrAreaOnRightAxis} diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 57e13f649a365..21b3f6e83ac6c 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -23460,7 +23460,6 @@ "xpack.lens.shared.tickLabels": "Étiquettes de graduation", "xpack.lens.shared.ticksPositionOptions": "Coches sur les bandes", "xpack.lens.shared.ticksPositionOptionsTooltip": "Place les coches sur chaque bordure de bande au lieu de les répartir de manière homogène.", - "xpack.lens.shared.valueInLegendLabel": "Afficher la valeur", "xpack.lens.shared.valueLabelsVisibility.auto": "Masquer", "xpack.lens.shared.valueLabelsVisibility.inside": "Afficher", "xpack.lens.staticValue.headingLabel": "Placement", @@ -44622,4 +44621,4 @@ "xpack.serverlessObservability.nav.projectSettings": "Paramètres de projet", "xpack.serverlessObservability.nav.synthetics": "Synthetics" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 34bfbb83ecfe1..902b420e0098c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -23441,7 +23441,6 @@ "xpack.lens.shared.tickLabels": "目盛ラベル", "xpack.lens.shared.ticksPositionOptions": "帯の目盛", "xpack.lens.shared.ticksPositionOptionsTooltip": "目盛を均等に分布するのではなく、各帯の境界に目盛を表示します", - "xpack.lens.shared.valueInLegendLabel": "値を表示", "xpack.lens.shared.valueLabelsVisibility.auto": "非表示", "xpack.lens.shared.valueLabelsVisibility.inside": "表示", "xpack.lens.staticValue.headingLabel": "配置", @@ -44598,4 +44597,4 @@ "xpack.serverlessObservability.nav.projectSettings": "プロジェクト設定", "xpack.serverlessObservability.nav.synthetics": "Synthetics" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2b6307f7417bb..7c3f6e0ecea52 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -23474,7 +23474,6 @@ "xpack.lens.shared.tickLabels": "刻度标签", "xpack.lens.shared.ticksPositionOptions": "带上的刻度", "xpack.lens.shared.ticksPositionOptionsTooltip": "将刻度放在每个带边框上,而不是平均分布", - "xpack.lens.shared.valueInLegendLabel": "显示值", "xpack.lens.shared.valueLabelsVisibility.auto": "隐藏", "xpack.lens.shared.valueLabelsVisibility.inside": "显示", "xpack.lens.staticValue.headingLabel": "位置", @@ -44646,4 +44645,4 @@ "xpack.serverlessObservability.nav.projectSettings": "项目设置", "xpack.serverlessObservability.nav.synthetics": "Synthetics" } -} +} \ No newline at end of file diff --git a/x-pack/test/functional/apps/lens/group6/legend_statistics.ts b/x-pack/test/functional/apps/lens/group6/legend_statistics.ts index c5cf63c92b7bd..a6e8cf8a86510 100644 --- a/x-pack/test/functional/apps/lens/group6/legend_statistics.ts +++ b/x-pack/test/functional/apps/lens/group6/legend_statistics.ts @@ -26,12 +26,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const text = await legendElement.getVisibleText(); expect(text).to.eql(expectedText); } + async function expectLegendTableToHaveText(expectedText: string) { + const legendElement = await find.byCssSelector('.echLegendTable'); + const text = await legendElement.getVisibleText(); + expect(text).to.eql(expectedText); + } - describe('lens persisted and runtime state differences properties', () => { + describe('lens legend statistics', () => { before(async () => { await kibanaServer.importExport.load( 'x-pack/test/functional/fixtures/kbn_archiver/lens/legend_statistics' ); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json' + ); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/default' + ); await kibanaServer.uiSettings.update({ 'timepicker:timeDefaults': '{ "from": "2015-09-18T19:37:13.000Z", "to": "2015-09-22T23:30:30.000Z"}', @@ -39,40 +50,72 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.visualize.gotoVisualizationLandingPage({ forceRefresh: true }); }); - after(async () => { - await kibanaServer.uiSettings.unset('timepicker:timeDefaults'); - }); - describe('xy chart', () => { - it('shows values in legend for legacy valuesInLegend===true property and saves it correctly', async () => { - const title = 'xyValuesInLegendTrue'; - await loadSavedLens(title); - await expectLegendOneItem('Count of records', '2'); - await PageObjects.lens.save(title); - await loadSavedLens(title); - await expectLegendOneItem('Count of records', '2'); - }); + describe('xy chart legend statistics', () => { + it('shows table with legend statistics', async () => { + await loadSavedLens('lnsXYvis'); - it('does not show values in legend for legacy valuesInLegend===false prop', async () => { - await loadSavedLens('xyValuesInLegendFalse'); - await expectLegendOneItem('Count of records'); - }); - it('shows values in legend for legendStats===["values"] prop', async () => { - await loadSavedLens('xyLegendStats'); - await expectLegendOneItem('Count of records', '2'); + await PageObjects.lens.toggleToolbarPopover('lnsLegendButton'); + await PageObjects.lens.selectOptionFromComboBox('lnsLegendStatisticsSelect', [ + 'average', + 'minimum', + 'maximum', + ]); + + const tableText = `Avg +Min +Max +97.220.3.248 +19,755 +19,755 +19,755 +169.228.188.120 +18,994 +18,994 +18,994 +78.83.247.30 +17,246 +17,246 +17,246`; + + await expectLegendTableToHaveText(tableText); }); }); - describe('waffle chart', () => { - it('waffleshows values in legend for legacy valuesInLegend===true property', async () => { - await loadSavedLens('waffleValuesInLegendTrue'); - await expectLegendOneItem('Count of records', '14,003'); + describe('lens persisted and runtime state differences properties', () => { + after(async () => { + await kibanaServer.uiSettings.unset('timepicker:timeDefaults'); }); - it('shows values in legend for legacy showValuesInLegend===false prop', async () => { - await loadSavedLens('waffleValuesInLegendFalse'); - await expectLegendOneItem('Count of records', undefined); + describe('xy chart', () => { + it('shows values in legend for legacy valuesInLegend===true property and saves it correctly', async () => { + const title = 'xyValuesInLegendTrue'; + await loadSavedLens(title); + await expectLegendOneItem('Count of records', '2'); + await PageObjects.lens.save(title); + await loadSavedLens(title); + await expectLegendOneItem('Count of records', '2'); + }); + + it('does not show values in legend for legacy valuesInLegend===false prop', async () => { + await loadSavedLens('xyValuesInLegendFalse'); + await expectLegendOneItem('Count of records'); + }); + it('shows values in legend for legendStats===["values"] prop', async () => { + await loadSavedLens('xyLegendStats'); + await expectLegendOneItem('Count of records', '2'); + }); }); - it('shows values in legend for legendStats===["values"] prop', async () => { - await loadSavedLens('waffleLegendStats'); - await expectLegendOneItem('Count of records', '14,003'); + describe('waffle chart', () => { + it('waffleshows values in legend for legacy valuesInLegend===true property', async () => { + await loadSavedLens('waffleValuesInLegendTrue'); + await expectLegendOneItem('Count of records', '14,003'); + }); + it('shows values in legend for legacy showValuesInLegend===false prop', async () => { + await loadSavedLens('waffleValuesInLegendFalse'); + await expectLegendOneItem('Count of records', undefined); + }); + it('shows values in legend for legendStats===["values"] prop', async () => { + await loadSavedLens('waffleLegendStats'); + await expectLegendOneItem('Count of records', '14,003'); + }); }); }); }); diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 9a5680b8cdf3c..913396d5b64dc 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -120,10 +120,13 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }); }, - async selectOptionFromComboBox(testTargetId: string, name: string) { + async selectOptionFromComboBox(testTargetId: string, name: string | string[]) { const target = await testSubjects.find(testTargetId, 1000); await comboBox.openOptionsList(target); - await comboBox.setElement(target, name); + const names = Array.isArray(name) ? name : [name]; + for (const option of names) { + await comboBox.setElement(target, option); + } }, async configureQueryAnnotation(opts: { From 37426f0bdec3149db9a50cc13c79bccfe3e4e376 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Thu, 20 Jun 2024 09:19:18 +0200 Subject: [PATCH 127/127] Check compatible `cluster.routing.allocation.enable` only on reindex migrations (#186090) ## Summary Addresses https://github.com/elastic/kibana/issues/177831. The PR introduces specific steps to check that `cluster.routing.allocation.enable` has a suitable value for _reindex migrations_. Up until now, this check was done systematically after the `INIT` step. Now, a couple new dedicated steps have been introduced, which allow verifying this setting on _reindex migrations_ only (highlighted in orange): ![image](https://github.com/elastic/kibana/assets/25349407/07c7f0b4-fa11-4925-908a-3cb222685796) --- .../index.ts | 2 +- .../src/README.md | 740 ++++++++++++++---- ... check_cluster_routing_allocation.test.ts} | 16 +- ...ts => check_cluster_routing_allocation.ts} | 42 +- .../src/actions/index.ts | 6 +- .../src/model/model.test.ts | 402 +++++----- .../src/model/model.ts | 385 ++++----- .../src/next.ts | 5 +- .../src/state.ts | 10 + .../src/zdt/actions/index.ts | 3 +- .../src/zdt/model/model.test.ts | 4 +- .../src/zdt/model/stages/init.test.ts | 114 ++- .../src/zdt/model/stages/init.ts | 13 - .../src/zdt/next.ts | 2 +- .../migrations/group3/actions/actions.test.ts | 34 +- .../group3/actions/actions_test_suite.ts | 34 +- .../migrations/group5/active_delete.test.ts | 5 +- .../group5/dot_kibana_split.test.ts | 6 +- .../migrations/group5/skip_reindex.test.ts | 5 +- 19 files changed, 1168 insertions(+), 660 deletions(-) rename packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/{initialize_action.test.ts => check_cluster_routing_allocation.test.ts} (89%) rename packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/{initialize_action.ts => check_cluster_routing_allocation.ts} (57%) 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 49ae09a16e7bb..cdb8d29dd725a 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 @@ -24,7 +24,6 @@ export { calculateExcludeFilters, checkForUnknownDocs, waitForIndexStatus, - initAction, cloneIndex, waitForTask, updateAndPickupMappings, @@ -40,6 +39,7 @@ export { fetchIndices, waitForReindexTask, waitForPickupUpdatedMappingsTask, + checkClusterRoutingAllocationEnabled, } from './src/actions'; export type { OpenPitResponse, 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 f30b09fca6212..ebeea457bb622 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 @@ -1,95 +1,134 @@ + - [Introduction](#introduction) - [Algorithm steps](#algorithm-steps) - [INIT](#init) - [Next action](#next-action) - [New control state](#new-control-state) - - [CREATE_NEW_TARGET](#create_new_target) + - [CREATE\_NEW\_TARGET](#create_new_target) - [Next action](#next-action-1) - [New control state](#new-control-state-1) - - [LEGACY_SET_WRITE_BLOCK](#legacy_set_write_block) + - [LEGACY\_CHECK\_CLUSTER\_ROUTING\_ALLOCATION](#legacy_check_cluster_routing_allocation) - [Next action](#next-action-2) - [New control state](#new-control-state-2) - - [LEGACY_CREATE_REINDEX_TARGET](#legacy_create_reindex_target) + - [LEGACY\_SET\_WRITE\_BLOCK](#legacy_set_write_block) - [Next action](#next-action-3) - [New control state](#new-control-state-3) - - [LEGACY_REINDEX](#legacy_reindex) + - [LEGACY\_CREATE\_REINDEX\_TARGET](#legacy_create_reindex_target) - [Next action](#next-action-4) - [New control state](#new-control-state-4) - - [LEGACY_REINDEX_WAIT_FOR_TASK](#legacy_reindex_wait_for_task) + - [LEGACY\_REINDEX](#legacy_reindex) - [Next action](#next-action-5) - [New control state](#new-control-state-5) - - [LEGACY_DELETE](#legacy_delete) + - [LEGACY\_REINDEX\_WAIT\_FOR\_TASK](#legacy_reindex_wait_for_task) - [Next action](#next-action-6) - [New control state](#new-control-state-6) - - [WAIT_FOR_MIGRATION_COMPLETION](#wait_for_migration_completion) + - [LEGACY\_DELETE](#legacy_delete) - [Next action](#next-action-7) - [New control state](#new-control-state-7) - - [WAIT_FOR_YELLOW_SOURCE](#wait_for_yellow_source) + - [WAIT\_FOR\_MIGRATION\_COMPLETION](#wait_for_migration_completion) - [Next action](#next-action-8) - [New control state](#new-control-state-8) - - [UPDATE_SOURCE_MAPPINGS_PROPERTIES](#update_source_mappings_properties) + - [WAIT\_FOR\_YELLOW\_SOURCE](#wait_for_yellow_source) - [Next action](#next-action-9) - [New control state](#new-control-state-9) - - [SET_SOURCE_WRITE_BLOCK](#set_source_write_block) + - [UPDATE\_SOURCE\_MAPPINGS\_PROPERTIES](#update_source_mappings_properties) - [Next action](#next-action-10) - [New control state](#new-control-state-10) - - [CREATE_REINDEX_TEMP](#create_reindex_temp) + - [CLEANUP\_UNKNOWN\_AND\_EXCLUDED](#cleanup_unknown_and_excluded) - [Next action](#next-action-11) - [New control state](#new-control-state-11) - - [REINDEX_SOURCE_TO_TEMP_OPEN_PIT](#reindex_source_to_temp_open_pit) + - [CLEANUP\_UNKNOWN\_AND\_EXCLUDED\_WAIT\_FOR\_TASK](#cleanup_unknown_and_excluded_wait_for_task) - [Next action](#next-action-12) - [New control state](#new-control-state-12) - - [REINDEX_SOURCE_TO_TEMP_READ](#reindex_source_to_temp_read) + - [PREPARE\_COMPATIBLE\_MIGRATION](#prepare_compatible_migration) - [Next action](#next-action-13) - [New control state](#new-control-state-13) - - [REINDEX_SOURCE_TO_TEMP_TRANSFORM](#reindex_source_to_temp_transform) + - [REFRESH\_SOURCE](#refresh_source) - [Next action](#next-action-14) - [New control state](#new-control-state-14) - - [REINDEX_SOURCE_TO_TEMP_INDEX_BULK](#reindex_source_to_temp_index_bulk) + - [CHECK\_CLUSTER\_ROUTING\_ALLOCATION](#check_cluster_routing_allocation) - [Next action](#next-action-15) - [New control state](#new-control-state-15) - - [REINDEX_SOURCE_TO_TEMP_CLOSE_PIT](#reindex_source_to_temp_close_pit) + - [CHECK\_UNKNOWN\_DOCUMENTS](#check_unknown_documents) - [Next action](#next-action-16) - - [New control state](#new-control-state-16) - - [SET_TEMP_WRITE_BLOCK](#set_temp_write_block) + - [SET\_SOURCE\_WRITE\_BLOCK](#set_source_write_block) - [Next action](#next-action-17) - - [New control state](#new-control-state-17) - - [CLONE_TEMP_TO_TARGET](#clone_temp_to_target) + - [New control state](#new-control-state-16) + - [CREATE\_REINDEX\_TEMP](#create_reindex_temp) - [Next action](#next-action-18) - - [New control state](#new-control-state-18) - - [OUTDATED_DOCUMENTS_SEARCH](#outdated_documents_search) + - [New control state](#new-control-state-17) + - [REINDEX\_SOURCE\_TO\_TEMP\_OPEN\_PIT](#reindex_source_to_temp_open_pit) - [Next action](#next-action-19) - - [New control state](#new-control-state-19) - - [OUTDATED_DOCUMENTS_TRANSFORM](#outdated_documents_transform) + - [New control state](#new-control-state-18) + - [REINDEX\_SOURCE\_TO\_TEMP\_READ](#reindex_source_to_temp_read) - [Next action](#next-action-20) - - [New control state](#new-control-state-20) - - [CHECK_TARGET_MAPPINGS](#check_target_mappings) + - [New control state](#new-control-state-19) + - [REINDEX\_SOURCE\_TO\_TEMP\_TRANSFORM](#reindex_source_to_temp_transform) - [Next action](#next-action-21) - - [New control state](#new-control-state-21) - - [UPDATE_TARGET_MAPPINGS_PROPERTIES](#update_target_mappings_properties) + - [New control state](#new-control-state-20) + - [REINDEX\_SOURCE\_TO\_TEMP\_INDEX\_BULK](#reindex_source_to_temp_index_bulk) - [Next action](#next-action-22) - - [New control state](#new-control-state-22) - - [UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK](#update_target_mappings_properties_wait_for_task) + - [New control state](#new-control-state-21) + - [REINDEX\_SOURCE\_TO\_TEMP\_CLOSE\_PIT](#reindex_source_to_temp_close_pit) - [Next action](#next-action-23) - - [New control state](#new-control-state-23) - - [CHECK_VERSION_INDEX_READY_ACTIONS](#check_version_index_ready_actions) + - [New control state](#new-control-state-22) + - [SET\_TEMP\_WRITE\_BLOCK](#set_temp_write_block) - [Next action](#next-action-24) - - [New control state](#new-control-state-24) - - [MARK_VERSION_INDEX_READY](#mark_version_index_ready) + - [New control state](#new-control-state-23) + - [CLONE\_TEMP\_TO\_TARGET](#clone_temp_to_target) - [Next action](#next-action-25) - - [New control state](#new-control-state-25) - - [MARK_VERSION_INDEX_READY_CONFLICT](#mark_version_index_ready_conflict) + - [New control state](#new-control-state-24) + - [REFRESH\_TARGET](#refresh_target) - [Next action](#next-action-26) + - [New control state](#new-control-state-25) + - [OUTDATED\_DOCUMENTS\_SEARCH\_OPEN\_PIT](#outdated_documents_search_open_pit) + - [Next action](#next-action-27) - [New control state](#new-control-state-26) + - [OUTDATED\_DOCUMENTS\_SEARCH\_READ](#outdated_documents_search_read) + - [Next action](#next-action-28) + - [New control state](#new-control-state-27) + - [OUTDATED\_DOCUMENTS\_TRANSFORM](#outdated_documents_transform) + - [Next action](#next-action-29) + - [New control state](#new-control-state-28) + - [TRANSFORMED\_DOCUMENTS\_BULK\_INDEX](#transformed_documents_bulk_index) + - [Next action](#next-action-30) + - [New control state](#new-control-state-29) + - [OUTDATED\_DOCUMENTS\_SEARCH\_CLOSE\_PIT](#outdated_documents_search_close_pit) + - [Next action](#next-action-31) + - [New control state](#new-control-state-30) + - [OUTDATED\_DOCUMENTS\_REFRESH](#outdated_documents_refresh) + - [Next action](#next-action-32) + - [New control state](#new-control-state-31) + - [CHECK\_TARGET\_MAPPINGS](#check_target_mappings) + - [Next action](#next-action-33) + - [New control state](#new-control-state-32) + - [UPDATE\_TARGET\_MAPPINGS\_PROPERTIES](#update_target_mappings_properties) + - [Next action](#next-action-34) + - [New control state](#new-control-state-33) + - [UPDATE\_TARGET\_MAPPINGS\_PROPERTIES\_WAIT\_FOR\_TASK](#update_target_mappings_properties_wait_for_task) + - [Next action](#next-action-35) + - [New control state](#new-control-state-34) + - [CHECK\_VERSION\_INDEX\_READY\_ACTIONS](#check_version_index_ready_actions) + - [Next action](#next-action-36) + - [New control state](#new-control-state-35) + - [MARK\_VERSION\_INDEX\_READY](#mark_version_index_ready) + - [Next action](#next-action-37) + - [New control state](#new-control-state-36) + - [MARK\_VERSION\_INDEX\_READY\_CONFLICT](#mark_version_index_ready_conflict) + - [Next action](#next-action-38) + - [New control state](#new-control-state-37) + - [FATAL](#fatal) + - [DONE](#done) - [Manual QA Test Plan](#manual-qa-test-plan) - [1. Legacy pre-migration](#1-legacy-pre-migration) - [2. Plugins enabled/disabled](#2-plugins-enableddisabled) - - [Test scenario 1 (enable a plugin after migration):](#test-scenario-1-enable-a-plugin-after-migration) - - [Test scenario 2 (disable a plugin after migration):](#test-scenario-2-disable-a-plugin-after-migration) - - [Test scenario 3 (multiple instances, enable a plugin after migration):](#test-scenario-3-multiple-instances-enable-a-plugin-after-migration) - - [Test scenario 4 (multiple instances, mixed plugin enabled configs):](#test-scenario-4-multiple-instances-mixed-plugin-enabled-configs) + - [Test scenario 1 (enable a plugin after migration)](#test-scenario-1-enable-a-plugin-after-migration) + - [Test scenario 2 (disable a plugin after migration)](#test-scenario-2-disable-a-plugin-after-migration) + - [Test scenario 3 (multiple instances, enable a plugin after migration)](#test-scenario-3-multiple-instances-enable-a-plugin-after-migration) + - [Test scenario 4 (multiple instances, mixed plugin enabled configs)](#test-scenario-4-multiple-instances-mixed-plugin-enabled-configs) # Introduction + In the past, the risk of downtime caused by Kibana's saved object upgrade migrations have discouraged users from adopting the latest features. v2 migrations aims to solve this problem by minimizing the operational impact on @@ -108,17 +147,18 @@ migrations RFC](https://github.com/elastic/kibana/blob/main/rfcs/text/0013_saved_object_migrations.md). # Algorithm steps + The design goals for the algorithm was to keep downtime below 10 minutes for 100k saved objects while guaranteeing no data loss and keeping steps as simple and explicit as possible. -The algorithm is implemented as a state-action machine based on https://www.microsoft.com/en-us/research/uploads/prod/2016/12/Computation-and-State-Machines.pdf +The algorithm is implemented as a *state-action machine*, based on The state-action machine defines it's behaviour in steps. Each step is a transition from a control state s_i to the contral state s_i+1 caused by an action a_i. -``` +```text s_i -> a_i -> s_i+1 s_i+1 -> a_i+1 -> s_i+2 ``` @@ -129,7 +169,8 @@ response to determine the next state to transition to as defined by the function `model(state, response)`. We can then loosely define a step as: -``` + +```javascript s_i+1 = model(s_i, await next(s_i)()) ``` @@ -138,8 +179,9 @@ terminates such as in the DONE and FATAL control states. What follows is a list of all control states. For each control state the following is described: - - _next action_: the next action triggered by the current control state - - _new control state_: based on the action response, the possible new control states that the machine will transition to + +- *next action*: the next action triggered by the current control state +- *new control state*: based on the action response, the possible new control states that the machine will transition to Since the algorithm runs once for each saved object index the steps below always reference a single saved object index `.kibana`. When Kibana starts up, @@ -147,14 +189,8 @@ all the steps are also repeated for the `.kibana_task_manager` index but this is left out of the description for brevity. ## INIT -### Next action -`initAction` - -Check that replica allocation is enabled from cluster settings (`cluster.routing.allocation.enabled`). Migrations will fail when replica allocation is disabled during the bulk index operation that waits for all active shards. Migrations wait for all active shards to ensure that saved objects are replicated to protect against data loss. -The Elasticsearch documentation mentions switching off replica allocation when restoring a cluster and this is a setting that might be overlooked when a restore is done. Migrations will fail early if replica allocation is incorrectly set to avoid adding a write block to the old index before running into a failure later. - -If replica allocation is set to 'all', the migration continues to fetch the saved object indices: +### Next action `fetchIndices` @@ -163,53 +199,77 @@ and determine whether we’re migrating from a legacy index or a v1 migrations index. ### New control state -1. Two conditions have to be met before migrations begin: - 1. The Elasticsearch shard allocation cluster setting `cluster.routing.allocation.enable` needs to be unset or set to 'all'. When set to 'primaries', 'new_primaries' or 'none', the migration will timeout when waiting for index green status before bulk indexing because the replica cannot be allocated. - As per the Elasticsearch docs https://www.elastic.co/guide/en/elasticsearch/reference/8.2/restart-cluster.html#restart-cluster-rolling when Cloud performs a rolling restart such as during an upgrade, it will temporarily disable shard allocation. Kibana therefore keeps retrying the INIT step to wait for shard allocation to be enabled again. +1. If `.kibana` is pointing to more than one index. - The check only considers persistent and transient settings and does not take static configuration in `elasticsearch.yml` into account since there are no known use cases for doing so. If `cluster.routing.allocation.enable` is configured in `elaticsearch.yml` and not set to the default of 'all', the migration will timeout. Static settings can only be returned from the `nodes/info` API. - → `INIT` + → [FATAL](#fatal) - 2. If `.kibana` is pointing to more than one index. - → `FATAL` - - 3. If `.kibana` is pointing to an index that belongs to a later version of +2. If `.kibana` is pointing to an index that belongs to a later version of Kibana .e.g. a 7.11.0 instance found the `.kibana` alias pointing to `.kibana_7.12.0_001` fail the migration - → `FATAL` -2. If `waitForMigrations` was set we're running on a background-tasks node and + → [FATAL](#fatal) + +3. If `waitForMigrations` was set we're running on a background-tasks node and we should not participate in the migration but instead wait for the ui node(s) to complete the migration. - → `WAIT_FOR_MIGRATION_COMPLETION` -3. If the `.kibana` alias exists we’re migrating from either a v1 or v2 index + → [WAIT_FOR_MIGRATION_COMPLETION](#wait_for_migration_completion) + +4. If the `.kibana` alias exists we’re migrating from either a v1 or v2 index and the migration source index is the index the `.kibana` alias points to. - → `WAIT_FOR_YELLOW_SOURCE` -4. If `.kibana` is a concrete index, we’re migrating from a legacy index - → `LEGACY_SET_WRITE_BLOCK` + → [WAIT_FOR_YELLOW_SOURCE](#wait_for_yellow_source) + +5. If `.kibana` is a concrete index, we’re migrating from a legacy index + + → [LEGACY_SET_WRITE_BLOCK](#legacy_set_write_block) -5. If there are no `.kibana` indices, this is a fresh deployment. Initialize a +6. If there are no `.kibana` indices, this is a fresh deployment. Initialize a new saved objects index - → `CREATE_NEW_TARGET` + + → [CREATE_NEW_TARGET](#create_new_target) ## CREATE_NEW_TARGET + ### Next action + `createIndex` Create the target index. This operation is idempotent, if the index already exist, we wait until its status turns green ### New control state + 1. If the action succeeds - → `MARK_VERSION_INDEX_READY` + + → [MARK_VERSION_INDEX_READY](#mark_version_index_ready) + 2. If the action fails with a `index_not_green_timeout` - → `CREATE_NEW_TARGET` + → [CREATE_NEW_TARGET](#create_new_target) + +## LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION + +### Next action + +`checkClusterRoutingAllocationCompatible` + +Same description and behavior as [CHECK\_CLUSTER\_ROUTING\_ALLOCATION](#check_cluster_routing_allocation), for legacy flow. + +### New control state + +1. If `cluster.routing.allocation.enabled` has a compatible value. + + → [LEGACY_SET_WRITE_BLOCK](#legacy_set_write_block) + +2. If it has a value that will not allow creating new *saved object* indices. + + → [LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION](#legacy_check_cluster_routing_allocation) (retry) ## LEGACY_SET_WRITE_BLOCK + ### Next action + `setWriteBlock` Set a write block on the legacy index to prevent any older Kibana instances @@ -217,118 +277,312 @@ from writing to the index while the migration is in progress which could cause lost acknowledged writes. This is the first of a series of `LEGACY_*` control states that will: - - reindex the concrete legacy `.kibana` index into a `.kibana_pre6.5.0_001` index - - delete the concrete `.kibana` _index_ so that we're able to create a `.kibana` _alias_ + +- reindex the concrete legacy `.kibana` index into a `.kibana_pre6.5.0_001` index +- delete the concrete `.kibana` *index* so that we're able to create a `.kibana` *alias* ### New control state + 1. If the write block was successfully added - → `LEGACY_CREATE_REINDEX_TARGET` + + → [LEGACY_CREATE_REINDEX_TARGET](#legacy_create_reindex_target) + 2. If the write block failed because the index doesn't exist, it means another instance already completed the legacy pre-migration. Proceed to the next step. - → `LEGACY_CREATE_REINDEX_TARGET` + + → [LEGACY_CREATE_REINDEX_TARGET](#legacy_create_reindex_target) ## LEGACY_CREATE_REINDEX_TARGET + ### Next action + `createIndex` Create a new `.kibana_pre6.5.0_001` index into which we can reindex the legacy index. (Since the task manager index was converted from a data index into a saved objects index in 7.4 it will be reindexed into `.kibana_pre7.4.0_001`) + ### New control state + 1. If the index creation succeeds - → `LEGACY_REINDEX` + + → [LEGACY_REINDEX](#legacy_reindex) + 2. If the index creation task failed with a `index_not_green_timeout` - → `LEGACY_REINDEX_WAIT_FOR_TASK` + + → [LEGACY_REINDEX_WAIT_FOR_TASK](#legacy_reindex_wait_for_task) + ## LEGACY_REINDEX + ### Next action + `reindex` Let Elasticsearch reindex the legacy index into `.kibana_pre6.5.0_001`. (For the task manager index we specify a `preMigrationScript` to convert the original task manager documents into valid saved objects) + ### New control state - → `LEGACY_REINDEX_WAIT_FOR_TASK` +→ [LEGACY_REINDEX_WAIT_FOR_TASK](#legacy_reindex_wait_for_task) ## LEGACY_REINDEX_WAIT_FOR_TASK + ### Next action + `waitForReindexTask` Wait for up to 60s for the reindex task to complete. + ### New control state + 1. If the reindex task completed - → `LEGACY_DELETE` + + → [LEGACY_DELETE](#legacy_delete) + 2. If the reindex task failed with a `target_index_had_write_block` or `index_not_found_exception` another instance already completed this step - → `LEGACY_DELETE` + + → [LEGACY_DELETE](#legacy_delete) + 3. If the reindex task is still in progress - → `LEGACY_REINDEX_WAIT_FOR_TASK` + + → [LEGACY_REINDEX_WAIT_FOR_TASK](#legacy_reindex_wait_for_task) ## LEGACY_DELETE + ### Next action + `updateAliases` Use the updateAliases API to atomically remove the legacy index and create a new `.kibana` alias that points to `.kibana_pre6.5.0_001`. + ### New control state + 1. If the action succeeds - → `SET_SOURCE_WRITE_BLOCK` + + → [SET_SOURCE_WRITE_BLOCK](#set_source_write_block) + 2. If the action fails with `remove_index_not_a_concrete_index` or `index_not_found_exception` another instance has already completed this step. - → `SET_SOURCE_WRITE_BLOCK` + + → [SET_SOURCE_WRITE_BLOCK](#set_source_write_block) ## WAIT_FOR_MIGRATION_COMPLETION + ### Next action + `fetchIndices` + ### New control state + 1. If the ui node finished the migration - → `DONE` + + → [DONE](#done) + 2. Otherwise wait 2s and check again - → `WAIT_FOR_MIGRATION_COMPLETION` + + → [WAIT_FOR_MIGRATION_COMPLETION](#wait_for_migration_completion) ## WAIT_FOR_YELLOW_SOURCE + ### Next action + `waitForIndexStatus` (status='yellow') Wait for the source index to become yellow. This means the index's primary has been allocated and is ready for reading/searching. On a multi node cluster the replicas for this index might not be ready yet but since we're never writing to the source index it does not matter. ### New control state + 1. If the action succeeds - → `UPDATE_SOURCE_MAPPINGS_PROPERTIES` + + → [UPDATE_SOURCE_MAPPINGS_PROPERTIES](#update_source_mappings_properties) + 2. If the action fails with a `index_not_yellow_timeout` - → `WAIT_FOR_YELLOW_SOURCE` + + → [WAIT_FOR_YELLOW_SOURCE](#wait_for_yellow_source) ## UPDATE_SOURCE_MAPPINGS_PROPERTIES + ### Next action + `updateSourceMappingsProperties` This action checks for source mappings changes. And if there are some, it tries to patch the mappings. + - If there were no changes or the patch was successful, that reports either the changes are compatible or the source is already up to date, depending on the version migration completion state. Either way, it does not require a follow-up reindexing. - If the patch is failed and the version migration is incomplete, it reports an incompatible state that requires reindexing. - If the patch is failed and the version migration is complete, it reports an error as it means an incompatible mappings change in an already migrated environment. The latter usually happens when a new plugin is enabled that brings some incompatible changes or when there are incompatible changes in the development environment. ### New control state + 1. If the mappings are updated and the migration is already completed. - → `OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT` + + → [OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT](#outdated_documents_search_open_pit) + 2. If the mappings are updated and the migration is still in progress. - → `CLEANUP_UNKNOWN_AND_EXCLUDED` + + → [CLEANUP_UNKNOWN_AND_EXCLUDED](#cleanup_unknown_and_excluded) + 3. If the mappings are not updated due to incompatible changes and the migration is still in progress. - → `CHECK_UNKNOWN_DOCUMENTS` + + → [CHECK_CLUSTER_ROUTING_ALLOCATION](#check_cluster_routing_allocation) + 4. If the mappings are not updated due to incompatible changes and the migration is already completed. - → `FATAL` + + → [FATAL](#fatal) + +## CLEANUP_UNKNOWN_AND_EXCLUDED + +### Next action + +`cleanupUnknownAndExcluded` + +This action searches for and deletes *saved objects* which are of unknown or excluded type. + +- Saved objects become unknown when their type is no longer registered in the *typeRegistry*. This can happen when disabling plugins. +- Also, saved objects can be excluded from upgrade with the `excludeOnUpgrade` flag in their type definition. + +In order to allow Kibana to discard unknown saved objects, users must set the [migrations.discardUnknownObjects](https://www.elastic.co/guide/en/kibana/current/resolve-migrations-failures.html#unknown-saved-object-types) flag. + +### New control state + +1. If unknown docs are found and Kibana is not configured to ignore them. + + → [FATAL](#fatal) + +2. If the delete operation is launched and we can wait for it. + + → [CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK](#cleanup_unknown_and_excluded_wait_for_task) + +## CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK + +### Next action + +`waitForDeleteByQueryTask` + +The cleanup task on the previous step is launched asynchronously, tracked by a specific `taskId`. On this step, we actively wait for it to finish, and we do that with a large timeout. + +### New control state + +1. If the task finishes before the timeout. + + → [PREPARE_COMPATIBLE_MIGRATION](#prepare_compatible_migration) + +2. If we hit the timeout whilst waiting for the task to be completed, but we still have some retry attempts left. + + → [CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK](#cleanup_unknown_and_excluded_wait_for_task) + +3. If some errors occur whilst cleaning up, there could be other instances performing the cleanup in parallel, deleting the documents that we intend to delete. In that scenario, we will launch the operation again. + + → [CLEANUP_UNKNOWN_AND_EXCLUDED](#cleanup_unknown_and_excluded) + +4. If we hit the timeout and we run out of retries. + + → [FATAL](#fatal) + +## PREPARE_COMPATIBLE_MIGRATION + +### Next action + +`updateAliases` + +At this point, we have successfully updated the index mappings. We are performing a *compatible migration*, aka updating *saved objects* in place on the existing index. In order to prevent other Kibana instances from writing documents whilst we update them, we remove the previous version alias. We also set set the current version alias, which will cause other instances' migrators to directly perform an *up-to-date migration*. + +### New control state + +1. If the aliases are updated successfully and some documents have been deleted on the previous step. + + → [REFRESH_SOURCE](#refresh_source) + +2. If the aliases are updated successfully and we did not delete any documents on the previous step. + + → [OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT](#outdated_documents_search_open_pit) + +3. When unexpected errors occur when updating the aliases. + + → [FATAL](#fatal) + +## REFRESH_SOURCE + +### Next action + +`refreshIndex` + +We are performing a *compatible migration*, and we discarded some unknown and excluded saved object documents. We must refresh the index so that subsequent queries no longer find these removed documents. + +### New control state + +1. If the index is refreshed successfully. + + → [OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT](#outdated_documents_search_open_pit) + +2. When unexpected errors occur during the refresh. + + → [FATAL](#fatal) + +## CHECK_CLUSTER_ROUTING_ALLOCATION + +### Next action + +`checkClusterRoutingAllocationEnabled` + +Check that replica allocation is enabled from cluster settings (`cluster.routing.allocation.enabled`). Migrations will fail when replica allocation is disabled during the bulk index operation that waits for all active shards. Migrations wait for all active shards to ensure that saved objects are replicated to protect against data loss. + +The Elasticsearch documentation mentions switching off replica allocation when restoring a cluster and this is a setting that might be overlooked when a restore is done. Migrations will fail early if replica allocation is incorrectly set to avoid adding a write block to the old index before running into a failure later. + +If replica allocation is set to 'all', the migration continues to fetch the saved object indices. + +### New control state + +The Elasticsearch shard allocation cluster setting `cluster.routing.allocation.enable` needs to be unset or set to 'all'. When set to 'primaries', 'new_primaries' or 'none', the migration will timeout when waiting for index green status before bulk indexing because the replica cannot be allocated. + +As per the Elasticsearch [docs](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/restart-cluster.html#restart-cluster-rolling), when Cloud performs a rolling restart such as during an upgrade, it will temporarily disable shard allocation. Kibana therefore keeps retrying the INIT step to wait for shard allocation to be enabled again. + +The check only considers persistent and transient settings and does not take static configuration in `elasticsearch.yml` into account since there are no known use cases for doing so. If `cluster.routing.allocation.enable` is configured in `elaticsearch.yml` and not set to the default of 'all', the migration will timeout. Static settings can only be returned from the `nodes/info` API. + +1. If `cluster.routing.allocation.enabled` has a compatible value. + + → [CHECK_UNKNOWN_DOCUMENTS](#check_unknown_documents) + +2. If it has a value that will not allow creating new *saved object* indices. + + → [CHECK_CLUSTER_ROUTING_ALLOCATION](#check_cluster_routing_allocation) (retry) + +## CHECK_UNKNOWN_DOCUMENTS + +Saved objects are unknown when their type is not registered in the *typeRegistry*. This can happen when disabling plugins, or when deprecated plugins are removed during a major upgrade. + +During a *reindex migration*, these documents can be discarded if Kibana is configured with the [migrations.discardUnknownObjects](https://www.elastic.co/guide/en/kibana/current/resolve-migrations-failures.html#unknown-saved-object-types) flag. + +### Next action + +1. If no unknown documents are found, or Kibana is configured to discard them. + + → [SET_SOURCE_WRITE_BLOCK](#set_source_write_block) + +2. If some unknown documents are found and Kibana is NOT configured to discard them. + + → [FATAL](#fatal) ## SET_SOURCE_WRITE_BLOCK + ### Next action + `setWriteBlock` Set a write block on the source index to prevent any older Kibana instances from writing to the index while the migration is in progress which could cause lost acknowledged writes. ### New control state - → `CREATE_REINDEX_TEMP` + +→ [CREATE_REINDEX_TEMP](#create_reindex_temp) ## CREATE_REINDEX_TEMP + ### Next action + `createIndex` This operation is idempotent, if the index already exist, we wait until its status turns green. @@ -337,33 +591,49 @@ This operation is idempotent, if the index already exist, we wait until its stat - (Since we never query the temporary index we can potentially disable refresh to speed up indexing performance. Profile to see if gains justify complexity) ### New control state + 1. If the action succeeds - → `REINDEX_SOURCE_TO_TEMP_OPEN_PIT` + + → [REINDEX_SOURCE_TO_TEMP_OPEN_PIT](#reindex_source_to_temp_open_pit) + 2. If the action fails with a `index_not_green_timeout` - → `CREATE_REINDEX_TEMP` + + → [CREATE_REINDEX_TEMP](#create_reindex_temp) ## REINDEX_SOURCE_TO_TEMP_OPEN_PIT + ### Next action + `openPIT` Open a PIT. Since there is a write block on the source index there is basically no overhead to keeping the PIT so we can lean towards a larger `keep_alive` value like 10 minutes. + ### New control state - → `REINDEX_SOURCE_TO_TEMP_READ` + +→ [REINDEX_SOURCE_TO_TEMP_READ](#reindex_source_to_temp_read) ## REINDEX_SOURCE_TO_TEMP_READ + ### Next action + `readNextBatchOfSourceDocuments` Read the next batch of outdated documents from the source index by using search after with our PIT. ### New control state + 1. If the batch contained > 0 documents - → `REINDEX_SOURCE_TO_TEMP_TRANSFORM` + + → [REINDEX_SOURCE_TO_TEMP_TRANSFORM](#reindex_source_to_temp_transform) + 2. If there are no more documents returned - → `REINDEX_SOURCE_TO_TEMP_CLOSE_PIT` + + → [REINDEX_SOURCE_TO_TEMP_CLOSE_PIT](#reindex_source_to_temp_close_pit) ## REINDEX_SOURCE_TO_TEMP_TRANSFORM + ### Next action + `transformRawDocs` Transform the current batch of documents @@ -372,10 +642,15 @@ In order to support sharing saved objects to multiple spaces in 8.0, the transforms will also regenerate document `_id`'s. To ensure that this step remains idempotent, the new `_id` is deterministically generated using UUIDv5 ensuring that each Kibana instance generates the same new `_id` for the same document. + ### New control state - → `REINDEX_SOURCE_TO_TEMP_INDEX_BULK` + +→ [REINDEX_SOURCE_TO_TEMP_INDEX_BULK](#reindex_source_to_temp_index_bulk) + ## REINDEX_SOURCE_TO_TEMP_INDEX_BULK + ### Next action + `bulkIndexTransformedDocuments` Use the bulk API create action to write a batch of up-to-date documents. The @@ -386,32 +661,47 @@ step will ensure that the index is refreshed before we start serving traffic. The following errors are ignored because it means another instance already completed this step: - - documents already exist in the temp index - - temp index has a write block - - temp index is not found + +- documents already exist in the temp index +- temp index has a write block +- temp index is not found + ### New control state + 1. If `currentBatch` is the last batch in `bulkOperationBatches` - → `REINDEX_SOURCE_TO_TEMP_READ` + + → [REINDEX_SOURCE_TO_TEMP_READ](#reindex_source_to_temp_read) + 2. If there are more batches left in `bulkOperationBatches` - → `REINDEX_SOURCE_TO_TEMP_INDEX_BULK` + + → [REINDEX_SOURCE_TO_TEMP_INDEX_BULK](#reindex_source_to_temp_index_bulk) ## REINDEX_SOURCE_TO_TEMP_CLOSE_PIT + ### Next action + `closePIT` ### New control state - → `SET_TEMP_WRITE_BLOCK` + +→ [SET_TEMP_WRITE_BLOCK](#set_temp_write_block) ## SET_TEMP_WRITE_BLOCK + ### Next action + `setWriteBlock` Set a write block on the temporary index so that we can clone it. + ### New control state - → `CLONE_TEMP_TO_TARGET` + +→ [CLONE_TEMP_TO_TARGET](#clone_temp_to_target) ## CLONE_TEMP_TO_TARGET + ### Next action + `cloneIndex` Ask elasticsearch to clone the temporary index into the target index. If the target index already exists (because another node already started the clone operation), wait until the clone is complete by waiting for a green index status. @@ -419,13 +709,56 @@ Ask elasticsearch to clone the temporary index into the target index. If the tar We can’t use the temporary index as our target index because one instance can complete the migration, delete a document, and then a second instance starts the reindex operation and re-creates the deleted document. By cloning the temporary index and only accepting writes/deletes from the cloned target index, we prevent lost acknowledged deletes. ### New control state -1. If the action succeeds - → `OUTDATED_DOCUMENTS_SEARCH` -2. If the action fails with a `index_not_green_timeout` - → `CLONE_TEMP_TO_TARGET` -## OUTDATED_DOCUMENTS_SEARCH +1. If the action succeeds. + + → [REFRESH_TARGET](#refresh_target) + +2. If the action fails with an `index_not_green_timeout`. + + → [CLONE_TEMP_TO_TARGET](#clone_temp_to_target) + +## REFRESH_TARGET + +### Next action + +`refreshIndex` + +We refresh the temporary clone index, to make sure newly added documents are taken into account. + +### New control state + +1. If the index is refreshed successfully. + + → [OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT](#outdated_documents_search_open_pit) + +2. When unexpected errors occur during the refresh. + + → [FATAL](#fatal) + +## OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT + +### Next action + +`openPit` + +Any saved objects that belong to previous versions are updated in the index. +This operation is performed in batches, leveraging the [Point in Time API](https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html). + +### New control state + +1. If the PIT is created successfully. + + → [OUTDATED_DOCUMENTS_SEARCH_READ](#outdated_documents_search_read) + +2. When unexpected errors occur whilst creating the PIT. + + → [FATAL](#fatal) + +## OUTDATED_DOCUMENTS_SEARCH_READ + ### Next action + `readWithPit(outdatedDocumentsQuery)` Search for outdated saved object documents. Will return one batch of @@ -438,19 +771,100 @@ plugins were disabled by the instance that performed the and transform them to ensure that everything is up to date. ### New control state -1. Found outdated documents? - → `OUTDATED_DOCUMENTS_TRANSFORM` -2. All documents up to date - → `UPDATE_TARGET_MAPPINGS_PROPERTIES` + +1. Found outdated documents. + + → [OUTDATED_DOCUMENTS_TRANSFORM](#outdated_documents_transform) + +2. There aren't any outdated documents left to read, and we can proceed with the flow. + + → [OUTDATED_DOCUMENTS_SEARCH_CLOSE_PIT](#outdated_documents_search_close_pit) + +3. There aren't any outdated documents left to read, but we encountered *corrupt* documents or *transform errors*, and Kibana is not configured to ignore them (using `migrations.discardCorruptObjects` flag). + + → [FATAL](#fatal) + +4. If we encounter an error of the form `es_response_too_large` whilst reading *saved object* documents, we retry with a smaller batch size. + + → [OUTDATED_DOCUMENTS_SEARCH_READ](#outdated_documents_search_read) ## OUTDATED_DOCUMENTS_TRANSFORM + +### Next action + +`transformDocs` + +### New control state + +1. If all of the outdated documents in the current batch are transformed successfully, or Kibana is configured to ignore *corrupt* documents and *transform* errors. We managed to break down the current set of documents into smaller batches successfully, so we can start indexing them one by one. + + → [TRANSFORMED_DOCUMENTS_BULK_INDEX](#transformed_documents_bulk_index) + +2. If the batch contains corrupt documents or transform errors, and Kibana is not configured to discard them, we do not index them, we simply read the next batch, accumulating encountered errors. + + → [OUTDATED_DOCUMENTS_SEARCH_READ](#outdated_documents_search_read) + +3. If we can't split the set of documents in batches small enough to not exceed the `maxBatchSize`, we fail the migration. + + → [FATAL](#fatal) + +## TRANSFORMED_DOCUMENTS_BULK_INDEX + +### Next action + +`bulkOverwriteTransformedDocuments` + +Once transformed we use an index operation to overwrite the outdated document with the up-to-date version. Optimistic concurrency control ensures that we only overwrite the document once so that any updates/writes by another instance which already completed the migration aren’t overwritten and lost. The transformed documents are split in different batches, and then each batch is bulk indexed. + +### New control state + +1. We have more batches to bulk index. + + → [TRANSFORMED_DOCUMENTS_BULK_INDEX](#transformed_documents_bulk_index) + +2. We have indexed all the batches of the current read operation. Proceed to read more documents. + + → [OUTDATED_DOCUMENTS_SEARCH_READ](#outdated_documents_search_read) + +## OUTDATED_DOCUMENTS_SEARCH_CLOSE_PIT + +### Next action + +`closePit` + +After reading, transforming and bulk indexingn all saved objects, we can close our PIT. + +### New control state + +1. If we can close the PIT successfully, and we did update some documents. + + → [OUTDATED_DOCUMENTS_REFRESH](#outdated_documents_refresh) + +2. If we can close the PIT successfully, and we did not update any documents. + + → [CHECK_TARGET_MAPPINGS](#check_target_mappings) + +3. An unexpected error occurred whilst closing the PIT. + + → [FATAL](#fatal) + +## OUTDATED_DOCUMENTS_REFRESH + ### Next action -`transformRawDocs` + `bulkOverwriteTransformedDocuments` -Once transformed we use an index operation to overwrite the outdated document with the up-to-date version. Optimistic concurrency control ensures that we only overwrite the document once so that any updates/writes by another instance which already completed the migration aren’t overwritten and lost. +`refreshIndex` + +We updated some outdated documents, we must refresh the target index to pick up the changes. ### New control state - → `OUTDATED_DOCUMENTS_SEARCH` + +1. If the index is refreshed successfully. + + → [CHECK_TARGET_MAPPINGS](#check_target_mappings) + +2. When unexpected errors occur during the refresh.**** + + → [FATAL](#fatal) ## CHECK_TARGET_MAPPINGS @@ -463,26 +877,35 @@ Compare the calculated mappings' hashes against those stored in the `.map ### New control state 1. If calculated mappings don't match, we must update them. - → `UPDATE_TARGET_MAPPINGS_PROPERTIES` + + → [UPDATE_TARGET_MAPPINGS_PROPERTIES](#update_target_mappings_properties) + 2. If calculated mappings and stored mappings match, we can skip directly to the next step. - → `CHECK_VERSION_INDEX_READY_ACTIONS` + + → [CHECK_VERSION_INDEX_READY_ACTIONS](#check_version_index_ready_actions) ## UPDATE_TARGET_MAPPINGS_PROPERTIES + ### Next action + `updateAndPickupMappings` If another instance has some plugins disabled it will disable the mappings of that plugin's types when creating the temporary index. This action will update the mappings and then use an update_by_query to ensure that all fields are “picked-up” and ready to be searched over. ### New control state - → `UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK` + +→ [UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK](#update_target_mappings_properties_wait_for_task) ## UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK + ### Next action + `waitForPickupUpdatedMappingsTask` ### New control state - → `MARK_VERSION_INDEX_READY` + +→ [MARK_VERSION_INDEX_READY](#mark_version_index_ready) ## CHECK_VERSION_INDEX_READY_ACTIONS @@ -495,12 +918,17 @@ None ### New control state 1. If there are some `versionIndexReadyActions`, we performed a full migration and need to point the aliases to our newly migrated index. - → `MARK_VERSION_INDEX_READY` + + → [MARK_VERSION_INDEX_READY](#mark_version_index_ready) + 2. If there are no `versionIndexReadyActions`, another instance already completed this migration and we only transformed outdated documents and updated the mappings for in case a new plugin was enabled. - → `DONE` + + → [DONE](#done) ## MARK_VERSION_INDEX_READY + ### Next action + `updateAliases` Atomically apply the `versionIndexReadyActions` using the _alias actions API. By performing the following actions we guarantee that if multiple versions of Kibana started the upgrade in parallel, only one version will succeed. @@ -510,40 +938,62 @@ Atomically apply the `versionIndexReadyActions` using the _alias actions API. By 3. Remove the temporary index ### New control state + 1. If all the actions succeed we’re ready to serve traffic - → `DONE` + + → [DONE](#done) + 2. If action (1) fails with alias_not_found_exception or action (3) fails with index_not_found_exception another instance already completed the migration - → `MARK_VERSION_INDEX_READY_CONFLICT` + + → [MARK_VERSION_INDEX_READY_CONFLICT](#mark_version_index_ready_conflict) ## MARK_VERSION_INDEX_READY_CONFLICT + ### Next action + `fetchIndices` Fetch the saved object indices ### New control state + If another instance completed a migration from the same source we need to verify that it is running the same version. 1. If the current and version aliases are pointing to the same index the instance that completed the migration was on the same version and it’s safe to start serving traffic. - → `DONE` + + → [DONE](#done) + 2. If the other instance was running a different version we fail the migration. Once we restart one of two things can happen: the other instance is an older version and we will restart the migration, or, it’s a newer version and we will refuse to start up. - → `FATAL` + + → [FATAL](#fatal) + +## FATAL + +Unfortunately, this migrator failed at some step. Please check the logs and identify the cause. Once addressed, restart Kibana again to restart / resume the migration. + +## DONE + +Congratulations, this migrator finished the saved objects migration for its index. # Manual QA Test Plan + ## 1. Legacy pre-migration + When upgrading from a legacy index additional steps are required before the regular migration process can start. We have the following potential legacy indices: - - v5.x index that wasn't upgraded -> kibana should refuse to start the migration - - v5.x index that was upgraded to v6.x: `.kibana-6` _index_ with `.kibana` _alias_ - - < v6.5 `.kibana` _index_ (Saved Object Migrations were - introduced in v6.5 https://github.com/elastic/kibana/pull/20243) - - TODO: Test versions which introduced the `kibana_index_template` template? - - < v7.4 `.kibana_task_manager` _index_ (Task Manager started - using Saved Objects in v7.4 https://github.com/elastic/kibana/pull/39829) + +- v5.x index that wasn't upgraded -> kibana should refuse to start the migration +- v5.x index that was upgraded to v6.x: `.kibana-6` *index* with `.kibana` *alias* +- < v6.5 `.kibana` *index* (Saved Object Migrations were + introduced in v6.5 ) +- TODO: Test versions which introduced the `kibana_index_template` template? +- < v7.4 `.kibana_task_manager` *index* (Task Manager started + using Saved Objects in v7.4 ) Test plan: + 1. Ensure that the different versions of Kibana listed above can successfully upgrade to 7.11. 2. Ensure that multiple Kibana nodes can migrate a legacy index in parallel @@ -565,6 +1015,7 @@ Test plan: successfully complete the migration. For a successful migration the following behaviour should be observed: + 1. The `.kibana` index should be reindexed into a `.kibana_pre6.5.0` index 2. The `.kibana` index should be deleted 3. The `.kibana_index_template` should be deleted @@ -574,11 +1025,13 @@ For a successful migration the following behaviour should be observed: aliases should point to the `.kibana_7.11.0_001` index. ## 2. Plugins enabled/disabled + Kibana plugins can be disabled/enabled at any point in time. We need to ensure that Saved Object documents are migrated for all the possible sequences of enabling, disabling, before or after a version upgrade. -### Test scenario 1 (enable a plugin after migration): +### Test scenario 1 (enable a plugin after migration) + 1. Start an old version of Kibana (< 7.11) 2. Create a document that we know will be migrated in a later version (i.e. create a `dashboard`) @@ -589,23 +1042,27 @@ enabling, disabling, before or after a version upgrade. 7. Ensure that the document from step (2) has been migrated (`migrationVersion` contains 7.11.0) -### Test scenario 2 (disable a plugin after migration): +### Test scenario 2 (disable a plugin after migration) + 1. Start an old version of Kibana (< 7.11) 2. Create a document that we know will be migrated in a later version (i.e. create a `dashboard`) 3. Upgrade Kibana to v7.11 making sure the plugin in step (3) is enabled. 4. Disable the plugin to which the document belongs (i.e `dashboard` plugin) -6. Restart Kibana -7. Ensure that Kibana logs a warning, but continues to start even though there +5. Restart Kibana +6. Ensure that Kibana logs a warning, but continues to start even though there are saved object documents which don't belong to an enable plugin -### Test scenario 3 (multiple instances, enable a plugin after migration): +### Test scenario 3 (multiple instances, enable a plugin after migration) + Follow the steps from 'Test scenario 1', but perform the migration with multiple instances of Kibana -### Test scenario 4 (multiple instances, mixed plugin enabled configs): +### Test scenario 4 (multiple instances, mixed plugin enabled configs) + We don't support this upgrade scenario, but it's worth making sure we don't have data loss when there's a user error. + 1. Start an old version of Kibana (< 7.11) 2. Create a document that we know will be migrated in a later version (i.e. create a `dashboard`) @@ -615,3 +1072,4 @@ have data loss when there's a user error. other half. 5. Ensure that the document from step (2) has been migrated (`migrationVersion` contains 7.11.0) + diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_cluster_routing_allocation.test.ts similarity index 89% rename from packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.test.ts rename to packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_cluster_routing_allocation.test.ts index 04ddcd3b78ce5..bce12671db8e4 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_cluster_routing_allocation.test.ts @@ -10,19 +10,13 @@ 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 { initAction, type InitActionParams } from './initialize_action'; +import { checkClusterRoutingAllocationEnabled } from './check_cluster_routing_allocation'; jest.mock('./catch_retryable_es_client_errors'); -describe('initAction', () => { - let initActionParams: Omit; - +describe('checkClusterRoutingAllocationEnabled', () => { beforeEach(() => { jest.clearAllMocks(); - - initActionParams = { - indices: ['.kibana', '.kibana_8.8.0'], - }; }); it('calls catchRetryableEsClientErrors when the promise rejects', async () => { const retryableError = new EsErrors.ResponseError( @@ -34,7 +28,7 @@ describe('initAction', () => { const client = elasticsearchClientMock.createInternalClient( elasticsearchClientMock.createErrorTransportRequestPromise(retryableError) ); - const task = initAction({ ...initActionParams, client }); + const task = checkClusterRoutingAllocationEnabled(client); try { await task(); } catch (e) { @@ -62,7 +56,7 @@ describe('initAction', () => { const client = elasticsearchClientMock.createInternalClient( Promise.resolve(clusterSettingsResponse) ); - const task = initAction({ ...initActionParams, client }); + const task = checkClusterRoutingAllocationEnabled(client); const result = await task(); expect(Either.isLeft(result)).toEqual(true); }); @@ -107,7 +101,7 @@ describe('initAction', () => { const client = elasticsearchClientMock.createInternalClient( Promise.resolve(clusterSettingsResponse) ); - const task = initAction({ ...initActionParams, client }); + const task = checkClusterRoutingAllocationEnabled(client); const result = await task(); expect(Either.isRight(result)).toEqual(true); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_cluster_routing_allocation.ts similarity index 57% rename from packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts rename to packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_cluster_routing_allocation.ts index 7db32f7a67d99..a64c03d91e219 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/initialize_action.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/check_cluster_routing_allocation.ts @@ -8,35 +8,22 @@ import * as TaskEither from 'fp-ts/lib/TaskEither'; import * as Either from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/function'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { catchRetryableEsClientErrors, type RetryableEsClientError, } from './catch_retryable_es_client_errors'; -import { type FetchIndexResponse, fetchIndices } from './fetch_indices'; - -const routingAllocationEnable = 'cluster.routing.allocation.enable'; -export interface ClusterRoutingAllocationEnabled { - clusterRoutingAllocationEnabled: boolean; -} - -export interface InitActionParams { - client: ElasticsearchClient; - indices: string[]; -} +const ROUTING_ALLOCATION_ENABLE = 'cluster.routing.allocation.enable'; export interface IncompatibleClusterRoutingAllocation { type: 'incompatible_cluster_routing_allocation'; } -export const checkClusterRoutingAllocationEnabledTask = - ({ - client, - }: { - client: ElasticsearchClient; - }): TaskEither.TaskEither => +export const checkClusterRoutingAllocationEnabled = + ( + client: ElasticsearchClient + ): TaskEither.TaskEither => () => { return client.cluster .getSettings({ @@ -45,8 +32,8 @@ export const checkClusterRoutingAllocationEnabledTask = .then((settings) => { // transient settings take preference over persistent settings const clusterRoutingAllocation = - settings?.transient?.[routingAllocationEnable] ?? - settings?.persistent?.[routingAllocationEnable]; + settings?.transient?.[ROUTING_ALLOCATION_ENABLE] ?? + settings?.persistent?.[ROUTING_ALLOCATION_ENABLE]; const clusterRoutingAllocationEnabledIsAll = clusterRoutingAllocation === undefined || clusterRoutingAllocation === 'all'; @@ -61,18 +48,3 @@ export const checkClusterRoutingAllocationEnabledTask = }) .catch(catchRetryableEsClientErrors); }; - -export const initAction = ({ - client, - indices, -}: InitActionParams): TaskEither.TaskEither< - RetryableEsClientError | IncompatibleClusterRoutingAllocation, - FetchIndexResponse -> => { - return pipe( - checkClusterRoutingAllocationEnabledTask({ client }), - TaskEither.chainW((value) => { - return fetchIndices({ client, indices }); - }) - ); -}; 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 84f37c96cca5f..35d05e1374667 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 @@ -21,8 +21,8 @@ export { export type { RetryableEsClientError }; // actions/* imports -export type { InitActionParams, IncompatibleClusterRoutingAllocation } from './initialize_action'; -export { initAction } from './initialize_action'; +export type { IncompatibleClusterRoutingAllocation } from './check_cluster_routing_allocation'; +export { checkClusterRoutingAllocationEnabled } from './check_cluster_routing_allocation'; export type { FetchIndexResponse, FetchIndicesParams } from './fetch_indices'; export { fetchIndices } from './fetch_indices'; @@ -108,7 +108,7 @@ export { } from './update_source_mappings_properties'; import type { UnknownDocsFound } from './check_for_unknown_docs'; -import type { IncompatibleClusterRoutingAllocation } from './initialize_action'; +import type { IncompatibleClusterRoutingAllocation } from './check_cluster_routing_allocation'; import type { ClusterShardLimitExceeded } from './create_index'; import type { SynchronizationFailed } from './synchronize_migrators'; import type { IndexMappingsIncomplete, TypesChanged } from './check_target_mappings'; 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 1980a6e6128db..961bc08e735ee 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 @@ -39,7 +39,6 @@ import type { OutdatedDocumentsSearchOpenPit, OutdatedDocumentsSearchRead, OutdatedDocumentsTransform, - PostInitState, PrepareCompatibleMigration, RefreshTarget, ReindexSourceToTempClosePit, @@ -57,6 +56,8 @@ import type { WaitForYellowSourceState, ReadyToReindexSyncState, DoneReindexingSyncState, + LegacyCheckClusterRoutingAllocationState, + CheckClusterRoutingAllocationState, } from '../state'; import { type TransformErrorObjects, TransformSavedObjectDocumentError } from '../core'; import type { AliasAction, RetryableEsClientError } from '../actions'; @@ -175,6 +176,7 @@ describe('migrations v2 model', () => { type: 'retryable_es_client_error', message: 'snapshot_in_progress_exception', }; + test('increments retryCount, exponential retryDelay if an action fails with a retryable_es_client_error', () => { const states = new Array(10).fill(1).map(() => { state = model(state, Either.left(retryableError)); @@ -301,49 +303,59 @@ describe('migrations v2 model', () => { }, } as const; - describe('if waitForMigrationCompletion=true', () => { - const initState = Object.assign({}, initBaseState, { - waitForMigrationCompletion: true, + test("INIT -> FATAL when .kibana points to newer version's index", () => { + const res: ResponseType<'INIT'> = Either.right({ + '.kibana_7.12.0_001': { + aliases: { + '.kibana': {}, + '.kibana_7.12.0': {}, + }, + mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, + settings: {}, + }, + '.kibana_7.11.0_001': { + aliases: { '.kibana_7.11.0': {} }, + mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, + settings: {}, + }, }); - test('INIT -> INIT when cluster routing allocation is incompatible', () => { - const res: ResponseType<'INIT'> = Either.left({ - type: 'incompatible_cluster_routing_allocation', - }); - const newState = model(initState, res) as FatalState; + const newState = model(initBaseState, res) as FatalState; - expect(newState.controlState).toEqual('INIT'); - expect(newState.retryCount).toEqual(1); - expect(newState.retryDelay).toEqual(2000); - expect(newState.logs[0]).toMatchInlineSnapshot(` - Object { - "level": "error", - "message": "Action failed with '[incompatible_cluster_routing_allocation] 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 routingAllocationDisabled for more information on how to resolve the issue.'. Retrying attempt 1 in 2 seconds.", - } - `); - }); - test("INIT -> FATAL when .kibana points to newer version's index", () => { - const res: ResponseType<'INIT'> = Either.right({ - '.kibana_7.12.0_001': { - aliases: { - '.kibana': {}, - '.kibana_7.12.0': {}, - }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - '.kibana_7.11.0_001': { - aliases: { '.kibana_7.11.0': {} }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, + expect(newState.controlState).toEqual('FATAL'); + expect(newState.reason).toMatchInlineSnapshot( + `"The .kibana alias is pointing to a newer version of Kibana: v7.12.0"` + ); + }); + + test('INIT -> FATAL when .kibana points to multiple indices', () => { + const res: ResponseType<'INIT'> = Either.right({ + '.kibana_7.12.0_001': { + aliases: { + '.kibana': {}, + '.kibana_7.12.0': {}, }, - }); - const newState = model(initState, res) as FatalState; + mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, + settings: {}, + }, + '.kibana_7.11.0_001': { + aliases: { '.kibana': {}, '.kibana_7.11.0': {} }, + mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, + settings: {}, + }, + }); + const newState = model(initBaseState, res) as FatalState; - expect(newState.controlState).toEqual('FATAL'); - expect(newState.reason).toMatchInlineSnapshot( - `"The .kibana alias is pointing to a newer version of Kibana: v7.12.0"` - ); + expect(newState.controlState).toEqual('FATAL'); + expect(newState.reason).toMatchInlineSnapshot( + `"The .kibana alias is pointing to multiple indices: .kibana_7.12.0_001,.kibana_7.11.0_001."` + ); + }); + + describe('if waitForMigrationCompletion=true', () => { + const initState = Object.assign({}, initBaseState, { + waitForMigrationCompletion: true, }); + test('INIT -> FATAL when later version alias exists', () => { const res: ResponseType<'INIT'> = Either.right({ '.kibana_7.11.0_001': { @@ -359,29 +371,7 @@ describe('migrations v2 model', () => { `"The .kibana_7.12.0 alias refers to a newer version of Kibana: v7.12.0"` ); }); - test('INIT -> FATAL when .kibana points to multiple indices', () => { - const res: ResponseType<'INIT'> = Either.right({ - '.kibana_7.12.0_001': { - aliases: { - '.kibana': {}, - '.kibana_7.12.0': {}, - }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - '.kibana_7.11.0_001': { - aliases: { '.kibana': {}, '.kibana_7.11.0': {} }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - }); - const newState = model(initState, res) as FatalState; - expect(newState.controlState).toEqual('FATAL'); - expect(newState.reason).toMatchInlineSnapshot( - `"The .kibana alias is pointing to multiple indices: .kibana_7.12.0_001,.kibana_7.11.0_001."` - ); - }); test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when .kibana points to an index with an invalid version', () => { // If users tamper with our index version naming scheme we can no // longer accurately detect a newer version. Older Kibana versions @@ -405,11 +395,12 @@ describe('migrations v2 model', () => { settings: {}, }, }); - const newState = model(initState, res) as WaitForYellowSourceState; + const newState = model(initState, res); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toBe(2000); }); + test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a v2 migrations index (>= 7.11.0)', () => { const res: ResponseType<'INIT'> = Either.right({ '.kibana_7.11.0_001': { @@ -431,11 +422,12 @@ describe('migrations v2 model', () => { versionIndex: '.kibana_7.12.0_001', }, res - ) as WaitForYellowSourceState; + ); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a v1 migrations index (>= 6.5 < 7.11.0)', () => { const res: ResponseType<'INIT'> = Either.right({ '.kibana_3': { @@ -446,11 +438,12 @@ describe('migrations v2 model', () => { settings: {}, }, }); - const newState = model(initState, res) as WaitForYellowSourceState; + const newState = model(initState, res); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a legacy index (>= 6.0.0 < 6.5)', () => { const res: ResponseType<'INIT'> = Either.right({ '.kibana': { @@ -464,6 +457,7 @@ describe('migrations v2 model', () => { expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a custom kibana.index name (>= 6.5 < 7.11.0)', () => { const res: ResponseType<'INIT'> = Either.right({ 'my-saved-objects_3': { @@ -483,11 +477,12 @@ describe('migrations v2 model', () => { versionIndex: 'my-saved-objects_7.11.0_001', }, res - ) as WaitForYellowSourceState; + ); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a custom kibana.index v2 migrations index (>= 7.11.0)', () => { const res: ResponseType<'INIT'> = Either.right({ 'my-saved-objects_7.11.0': { @@ -508,11 +503,12 @@ describe('migrations v2 model', () => { versionIndex: 'my-saved-objects_7.12.0_001', }, res - ) as WaitForYellowSourceState; + ); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('INIT -> WAIT_FOR_MIGRATION_COMPLETION when no indices/aliases exist', () => { const res: ResponseType<'INIT'> = Either.right({}); const newState = model(initState, res); @@ -526,68 +522,7 @@ describe('migrations v2 model', () => { const initState = Object.assign({}, initBaseState, { waitForMigrationCompletion: false, }); - test('INIT -> INIT when cluster routing allocation is incompatible', () => { - const res: ResponseType<'INIT'> = Either.left({ - type: 'incompatible_cluster_routing_allocation', - }); - const newState = model(initState, res) as FatalState; - expect(newState.controlState).toEqual('INIT'); - expect(newState.retryCount).toEqual(1); - expect(newState.retryDelay).toEqual(2000); - expect(newState.logs[0]).toMatchInlineSnapshot(` - Object { - "level": "error", - "message": "Action failed with '[incompatible_cluster_routing_allocation] 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 routingAllocationDisabled for more information on how to resolve the issue.'. Retrying attempt 1 in 2 seconds.", - } - `); - }); - test("INIT -> FATAL when .kibana points to newer version's index", () => { - const res: ResponseType<'INIT'> = Either.right({ - '.kibana_7.12.0_001': { - aliases: { - '.kibana': {}, - '.kibana_7.12.0': {}, - }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - '.kibana_7.11.0_001': { - aliases: { '.kibana_7.11.0': {} }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - }); - const newState = model(initState, res) as FatalState; - - expect(newState.controlState).toEqual('FATAL'); - expect(newState.reason).toMatchInlineSnapshot( - `"The .kibana alias is pointing to a newer version of Kibana: v7.12.0"` - ); - }); - test('INIT -> FATAL when .kibana points to multiple indices', () => { - const res: ResponseType<'INIT'> = Either.right({ - '.kibana_7.12.0_001': { - aliases: { - '.kibana': {}, - '.kibana_7.12.0': {}, - }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - '.kibana_7.11.0_001': { - aliases: { '.kibana': {}, '.kibana_7.11.0': {} }, - mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } }, - settings: {}, - }, - }); - const newState = model(initState, res) as FatalState; - - expect(newState.controlState).toEqual('FATAL'); - expect(newState.reason).toMatchInlineSnapshot( - `"The .kibana alias is pointing to multiple indices: .kibana_7.12.0_001,.kibana_7.11.0_001."` - ); - }); test('INIT -> WAIT_FOR_YELLOW_SOURCE when .kibana points to an index with an invalid version', () => { // If users tamper with our index version naming scheme we can no // longer accurately detect a newer version. Older Kibana versions @@ -675,7 +610,8 @@ describe('migrations v2 model', () => { '.kibana': '.kibana_3', }); }); - test('INIT -> LEGACY_SET_WRITE_BLOCK when migrating from a legacy index (>= 6.0.0 < 6.5)', () => { + + test('INIT -> LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION when migrating from a legacy index (>= 6.0.0 < 6.5)', () => { const res: ResponseType<'INIT'> = Either.right({ '.kibana': { aliases: {}, @@ -686,7 +622,7 @@ describe('migrations v2 model', () => { const newState = model(initState, res); expect(newState).toMatchObject({ - controlState: 'LEGACY_SET_WRITE_BLOCK', + controlState: 'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION', sourceIndex: Option.some('.kibana_pre6.5.0_001'), targetIndex: '.kibana_7.11.0_001', }); @@ -714,6 +650,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('INIT -> WAIT_FOR_YELLOW_SOURCE when migrating from a custom kibana.index name (>= 6.5 < 7.11.0)', () => { const res: ResponseType<'INIT'> = Either.right({ 'my-saved-objects_3': { @@ -740,6 +677,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('INIT -> WAIT_FOR_YELLOW_SOURCE when migrating from a custom kibana.index v2 migrations index (>= 7.11.0)', () => { const res: ResponseType<'INIT'> = Either.right({ 'my-saved-objects_7.11.0': { @@ -768,6 +706,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('INIT -> CREATE_NEW_TARGET when the index does not exist and the migrator is NOT involved in a relocation', () => { const res: ResponseType<'INIT'> = Either.right({}); const newState = model(initState, res); @@ -780,6 +719,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('INIT -> CREATE_REINDEX_TEMP when the index does not exist and the migrator is involved in a relocation', () => { const res: ResponseType<'INIT'> = Either.right({}); const newState = model( @@ -837,11 +777,12 @@ describe('migrations v2 model', () => { settings: {}, }, }); - const newState = model(waitForMState, res) as WaitForYellowSourceState; + const newState = model(waitForMState, res); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toBe(2000); }); + test('WAIT_FOR_MIGRATION_COMPLETION -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a v2 migrations index (>= 7.11.0)', () => { const res: ResponseType<'WAIT_FOR_MIGRATION_COMPLETION'> = Either.right({ '.kibana_7.11.0_001': { @@ -865,11 +806,12 @@ describe('migrations v2 model', () => { }, }, res - ) as WaitForYellowSourceState; + ); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('WAIT_FOR_MIGRATION_COMPLETION -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a v1 migrations index (>= 6.5 < 7.11.0)', () => { const res: ResponseType<'WAIT_FOR_MIGRATION_COMPLETION'> = Either.right({ '.kibana_3': { @@ -880,11 +822,12 @@ describe('migrations v2 model', () => { settings: {}, }, }); - const newState = model(waitForMState, res) as WaitForYellowSourceState; + const newState = model(waitForMState, res); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('WAIT_FOR_MIGRATION_COMPLETION -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a legacy index (>= 6.0.0 < 6.5)', () => { const res: ResponseType<'WAIT_FOR_MIGRATION_COMPLETION'> = Either.right({ '.kibana': { @@ -898,6 +841,7 @@ describe('migrations v2 model', () => { expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('WAIT_FOR_MIGRATION_COMPLETION -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a custom kibana.index name (>= 6.5 < 7.11.0)', () => { const res: ResponseType<'WAIT_FOR_MIGRATION_COMPLETION'> = Either.right({ 'my-saved-objects_3': { @@ -916,11 +860,12 @@ describe('migrations v2 model', () => { versionIndex: 'my-saved-objects_7.11.0_001', }, res - ) as WaitForYellowSourceState; + ); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('WAIT_FOR_MIGRATION_COMPLETION -> WAIT_FOR_MIGRATION_COMPLETION when migrating from a custom kibana.index v2 migrations index (>= 7.11.0)', () => { const res: ResponseType<'WAIT_FOR_MIGRATION_COMPLETION'> = Either.right({ 'my-saved-objects_7.11.0': { @@ -940,11 +885,12 @@ describe('migrations v2 model', () => { versionIndex: 'my-saved-objects_7.12.0_001', }, res - ) as WaitForYellowSourceState; + ); expect(newState.controlState).toBe('WAIT_FOR_MIGRATION_COMPLETION'); expect(newState.retryDelay).toEqual(2000); }); + test('WAIT_FOR_MIGRATION_COMPLETION -> WAIT_FOR_MIGRATION_COMPLETION when no indices/aliases exist', () => { const res: ResponseType<'WAIT_FOR_MIGRATION_COMPLETION'> = Either.right({}); const newState = model(waitForMState, res); @@ -970,6 +916,37 @@ describe('migrations v2 model', () => { }); }); + describe('LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION', () => { + const legacyCheckClusterRoutingAllocationState: LegacyCheckClusterRoutingAllocationState = { + ...postInitState, + controlState: 'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION', + sourceIndex: Option.some('.kibana') as Option.Some, + sourceIndexMappings: Option.some({ properties: {} }) as Option.Some, + legacyPreMigrationDoneActions: [], + legacyIndex: '', + }; + + test('LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION -> LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION when cluster allocation is not compatible', () => { + const res: ResponseType<'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION'> = Either.left({ + type: 'incompatible_cluster_routing_allocation', + }); + const newState = model(legacyCheckClusterRoutingAllocationState, res); + + expect(newState.controlState).toBe('LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION'); + expect(newState.retryCount).toEqual(1); + expect(newState.retryDelay).toEqual(2000); + }); + + test('LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION -> LEGACY_SET_WRITE_BLOCK when cluster allocation is compatible', () => { + const res: ResponseType<'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION'> = Either.right({}); + const newState = model(legacyCheckClusterRoutingAllocationState, res); + + expect(newState.controlState).toBe('LEGACY_SET_WRITE_BLOCK'); + expect(newState.retryCount).toEqual(0); + expect(newState.retryDelay).toEqual(0); + }); + }); + describe('LEGACY_SET_WRITE_BLOCK', () => { const legacySetWriteBlockState: LegacySetWriteBlockState = { ...postInitState, @@ -979,6 +956,7 @@ describe('migrations v2 model', () => { legacyPreMigrationDoneActions: [], legacyIndex: '', }; + test('LEGACY_SET_WRITE_BLOCK -> LEGACY_SET_WRITE_BLOCK if action fails with set_write_block_failed', () => { const res: ResponseType<'LEGACY_SET_WRITE_BLOCK'> = Either.left({ type: 'retryable_es_client_error', @@ -989,6 +967,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(1); expect(newState.retryDelay).toEqual(2000); }); + test('LEGACY_SET_WRITE_BLOCK -> LEGACY_CREATE_REINDEX_TARGET if action fails with index_not_found_exception', () => { const res: ResponseType<'LEGACY_SET_WRITE_BLOCK'> = Either.left({ type: 'index_not_found_exception', @@ -999,6 +978,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_SET_WRITE_BLOCK -> LEGACY_CREATE_REINDEX_TARGET if action succeeds with set_write_block_succeeded', () => { const res: ResponseType<'LEGACY_SET_WRITE_BLOCK'> = Either.right( 'set_write_block_succeeded' @@ -1019,6 +999,7 @@ describe('migrations v2 model', () => { legacyPreMigrationDoneActions: [], legacyIndex: '', }; + test('LEGACY_CREATE_REINDEX_TARGET -> LEGACY_REINDEX', () => { const res: ResponseType<'LEGACY_CREATE_REINDEX_TARGET'> = Either.right('create_index_succeeded'); @@ -1027,6 +1008,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_CREATE_REINDEX_TARGET -> LEGACY_CREATE_REINDEX_TARGET if action fails with index_not_green_timeout', () => { const res: ResponseType<'LEGACY_CREATE_REINDEX_TARGET'> = Either.left({ message: '[index_not_green_timeout] Timeout waiting for ...', @@ -1043,6 +1025,7 @@ describe('migrations v2 model', () => { } `); }); + test('LEGACY_CREATE_REINDEX_TARGET -> LEGACY_REINDEX resets retry count and retry delay if action succeeds', () => { const res: ResponseType<'LEGACY_CREATE_REINDEX_TARGET'> = Either.right('create_index_succeeded'); @@ -1056,13 +1039,14 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_CREATE_REINDEX_TARGET -> FATAL if action fails with cluster_shard_limit_exceeded', () => { const res: ResponseType<'LEGACY_CREATE_REINDEX_TARGET'> = Either.left({ type: 'cluster_shard_limit_exceeded', }); - const newState = model(legacyCreateReindexTargetState, res); + const newState = model(legacyCreateReindexTargetState, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); - expect((newState as FatalState).reason).toMatchInlineSnapshot( + expect(newState.reason).toMatchInlineSnapshot( `"[cluster_shard_limit_exceeded] Upgrading Kibana requires adding a small number of new shards. Ensure that Kibana is able to add 10 more shards by increasing the cluster.max_shards_per_node setting, or removing indices to clear up resources. See clusterShardLimitExceeded"` ); }); @@ -1077,6 +1061,7 @@ describe('migrations v2 model', () => { legacyPreMigrationDoneActions: [], legacyIndex: '', }; + test('LEGACY_REINDEX -> LEGACY_REINDEX_WAIT_FOR_TASK', () => { const res: ResponseType<'LEGACY_REINDEX'> = Either.right({ taskId: 'task id' }); const newState = model(legacyReindexState, res); @@ -1096,6 +1081,7 @@ describe('migrations v2 model', () => { legacyIndex: 'legacy_index_name', legacyReindexTaskId: 'test_task_id', }; + test('LEGACY_REINDEX_WAIT_FOR_TASK -> LEGACY_DELETE if action succeeds', () => { const res: ResponseType<'LEGACY_REINDEX_WAIT_FOR_TASK'> = Either.right('reindex_succeeded'); const newState = model(legacyReindexWaitForTaskState, res); @@ -1103,6 +1089,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_REINDEX_WAIT_FOR_TASK -> LEGACY_DELETE if action fails with index_not_found_exception for reindex source', () => { const res: ResponseType<'LEGACY_REINDEX_WAIT_FOR_TASK'> = Either.left({ type: 'index_not_found_exception', @@ -1113,6 +1100,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_REINDEX_WAIT_FOR_TASK -> LEGACY_DELETE if action fails with target_index_had_write_block', () => { const res: ResponseType<'LEGACY_REINDEX_WAIT_FOR_TASK'> = Either.left({ type: 'target_index_had_write_block', @@ -1122,6 +1110,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_REINDEX_WAIT_FOR_TASK -> LEGACY_REINDEX_WAIT_FOR_TASK if action fails with wait_for_task_completion_timeout', () => { const res: ResponseType<'LEGACY_REINDEX_WAIT_FOR_TASK'> = Either.left({ message: '[timeout_exception] Timeout waiting for ...', @@ -1132,6 +1121,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(1); expect(newState.retryDelay).toEqual(2000); }); + test('LEGACY_REINDEX_WAIT_FOR_TASK -> LEGACY_REINDEX_WAIT_FOR_TASK with incremented retryCount if action fails with wait_for_task_completion_timeout a second time', () => { const state = Object.assign({}, legacyReindexWaitForTaskState, { retryCount: 1 }); const res: ResponseType<'LEGACY_REINDEX_WAIT_FOR_TASK'> = Either.left({ @@ -1154,6 +1144,7 @@ describe('migrations v2 model', () => { legacyPreMigrationDoneActions: [], legacyIndex: 'legacy_index_name', }; + test('LEGACY_DELETE -> SET_SOURCE_WRITE_BLOCK if action succeeds', () => { const res: ResponseType<'LEGACY_DELETE'> = Either.right('update_aliases_succeeded'); const newState = model(legacyDeleteState, res); @@ -1161,6 +1152,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_DELETE -> SET_SOURCE_WRITE_BLOCK if action fails with index_not_found_exception for legacy index', () => { const res: ResponseType<'LEGACY_REINDEX_WAIT_FOR_TASK'> = Either.left({ type: 'index_not_found_exception', @@ -1171,6 +1163,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('LEGACY_DELETE -> SET_SOURCE_WRITE_BLOCK if action fails with remove_index_not_a_concrete_index', () => { const res: ResponseType<'LEGACY_DELETE'> = Either.left({ type: 'remove_index_not_a_concrete_index', @@ -1209,25 +1202,20 @@ describe('migrations v2 model', () => { test('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS_PROPERTIES', () => { const res: ResponseType<'WAIT_FOR_YELLOW_SOURCE'> = Either.right({}); const newState = model(waitForYellowSourceState, res); - - expect(newState).toMatchObject({ - controlState: 'UPDATE_SOURCE_MAPPINGS_PROPERTIES', - }); + expect(newState.controlState).toEqual('UPDATE_SOURCE_MAPPINGS_PROPERTIES'); }); }); describe('if the migrator is involved in a relocation', () => { // no need to attempt to update the mappings, we are going to reindex - test('WAIT_FOR_YELLOW_SOURCE -> CHECK_UNKNOWN_DOCUMENTS', () => { + test('WAIT_FOR_YELLOW_SOURCE -> CHECK_CLUSTER_ROUTING_ALLOCATION', () => { const res: ResponseType<'WAIT_FOR_YELLOW_SOURCE'> = Either.right({}); const newState = model( { ...waitForYellowSourceState, mustRelocateDocuments: true }, res ); - expect(newState).toMatchObject({ - controlState: 'CHECK_UNKNOWN_DOCUMENTS', - }); + expect(newState.controlState).toEqual('CHECK_CLUSTER_ROUTING_ALLOCATION'); }); }); }); @@ -1272,10 +1260,7 @@ describe('migrations v2 model', () => { 'update_mappings_succeeded' ); const newState = model(updateSourceMappingsPropertiesState, res); - - expect(newState).toMatchObject({ - controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', - }); + expect(newState.controlState).toEqual('CLEANUP_UNKNOWN_AND_EXCLUDED'); }); test('UPDATE_SOURCE_MAPPINGS_PROPERTIES -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT if mappings changes are compatible and index is already migrated', () => { @@ -1305,15 +1290,12 @@ describe('migrations v2 model', () => { }); describe('if action fails', () => { - test('UPDATE_SOURCE_MAPPINGS_PROPERTIES -> CHECK_UNKNOWN_DOCUMENTS if mappings changes are incompatible', () => { + test('UPDATE_SOURCE_MAPPINGS_PROPERTIES -> CHECK_CLUSTER_ROUTING_ALLOCATION if mappings changes are incompatible', () => { const res: ResponseType<'UPDATE_SOURCE_MAPPINGS_PROPERTIES'> = Either.left({ type: 'incompatible_mapping_exception', }); const newState = model(updateSourceMappingsPropertiesState, res); - - expect(newState).toMatchObject({ - controlState: 'CHECK_UNKNOWN_DOCUMENTS', - }); + expect(newState.controlState).toEqual('CHECK_CLUSTER_ROUTING_ALLOCATION'); }); test('UPDATE_SOURCE_MAPPINGS_PROPERTIES -> FATAL', () => { @@ -1326,11 +1308,12 @@ describe('migrations v2 model', () => { .set(['aliases', '.kibana'], '.kibana_7.11.0_001') .value(), res - ); + ) as FatalState; - expect(newState).toMatchObject({ - controlState: 'FATAL', - }); + expect(newState.controlState).toEqual('FATAL'); + expect(newState.reason).toMatchInlineSnapshot( + `"Incompatible mappings change on already migrated Kibana instance."` + ); }); }); }); @@ -1485,6 +1468,35 @@ describe('migrations v2 model', () => { }); }); + describe('CHECK_CLUSTER_ROUTING_ALLOCATION', () => { + const checkClusterRoutingAllocationState: CheckClusterRoutingAllocationState = { + ...postInitState, + controlState: 'CHECK_CLUSTER_ROUTING_ALLOCATION', + sourceIndex: Option.some('.kibana') as Option.Some, + sourceIndexMappings: Option.some({}) as Option.Some, + }; + + test('CHECK_CLUSTER_ROUTING_ALLOCATION -> CHECK_CLUSTER_ROUTING_ALLOCATION when cluster allocation is not compatible', () => { + const res: ResponseType<'CHECK_CLUSTER_ROUTING_ALLOCATION'> = Either.left({ + type: 'incompatible_cluster_routing_allocation', + }); + const newState = model(checkClusterRoutingAllocationState, res); + + expect(newState.controlState).toBe('CHECK_CLUSTER_ROUTING_ALLOCATION'); + expect(newState.retryCount).toEqual(1); + expect(newState.retryDelay).toEqual(2000); + }); + + test('CHECK_CLUSTER_ROUTING_ALLOCATION -> CHECK_UNKNOWN_DOCUMENTS when cluster allocation is compatible', () => { + const res: ResponseType<'CHECK_CLUSTER_ROUTING_ALLOCATION'> = Either.right({}); + const newState = model(checkClusterRoutingAllocationState, res); + + expect(newState.controlState).toBe('CHECK_UNKNOWN_DOCUMENTS'); + expect(newState.retryCount).toEqual(0); + expect(newState.retryDelay).toEqual(0); + }); + }); + describe('CHECK_UNKNOWN_DOCUMENTS', () => { const mappingsWithUnknownType = { properties: { @@ -1626,6 +1638,7 @@ describe('migrations v2 model', () => { sourceIndex: Option.some('.kibana') as Option.Some, sourceIndexMappings: Option.some({}) as Option.Some, }; + test('SET_SOURCE_WRITE_BLOCK -> SET_SOURCE_WRITE_BLOCK if action fails with set_write_block_failed', () => { const res: ResponseType<'SET_SOURCE_WRITE_BLOCK'> = Either.left({ type: 'retryable_es_client_error', @@ -1636,6 +1649,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(1); expect(newState.retryDelay).toEqual(2000); }); + test('SET_SOURCE_WRITE_BLOCK -> CALCULATE_EXCLUDE_FILTERS if action succeeds with set_write_block_succeeded', () => { const res: ResponseType<'SET_SOURCE_WRITE_BLOCK'> = Either.right( 'set_write_block_succeeded' @@ -1664,6 +1678,7 @@ describe('migrations v2 model', () => { sourceIndexMappings: Option.some({}) as Option.Some, tempIndexMappings: { properties: {} }, }; + test('CALCULATE_EXCLUDE_FILTERS -> CALCULATE_EXCLUDE_FILTERS if action fails with retryable error', () => { const res: ResponseType<'CALCULATE_EXCLUDE_FILTERS'> = Either.left({ type: 'retryable_es_client_error', @@ -1764,13 +1779,14 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('CREATE_REINDEX_TEMP -> FATAL if action fails with cluster_shard_limit_exceeded', () => { const res: ResponseType<'CREATE_REINDEX_TEMP'> = Either.left({ type: 'cluster_shard_limit_exceeded', }); - const newState = model(state, res); + const newState = model(state, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); - expect((newState as FatalState).reason).toMatchInlineSnapshot( + expect(newState.reason).toMatchInlineSnapshot( `"[cluster_shard_limit_exceeded] Upgrading Kibana requires adding a small number of new shards. Ensure that Kibana is able to add 10 more shards by increasing the cluster.max_shards_per_node setting, or removing indices to clear up resources. See clusterShardLimitExceeded"` ); }); @@ -1816,9 +1832,9 @@ describe('migrations v2 model', () => { type: 'synchronization_failed', error: new Error('Other migrators failed to reach the synchronization point'), }); - const newState = model(state, res); + const newState = model(state, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); - expect((newState as FatalState).reason).toMatchInlineSnapshot( + expect(newState.reason).toMatchInlineSnapshot( `"An error occurred whilst waiting for other migrators to get to this step."` ); }); @@ -1955,12 +1971,13 @@ describe('migrations v2 model', () => { contentLength: 2345, }); const newState = model({ ...state, batchSize: 1 }, res) as FatalState; - expect(newState.controlState).toBe('FATAL'); - expect(newState.batchSize).toBe(1); // don't halve the batch size or go below 1 - expect(newState.maxBatchSize).toBe(1000); // leaves maxBatchSize unchanged - expect(newState.reason).toMatchInlineSnapshot( - `"After reducing the read batch size to a single document, the Elasticsearch response content length was 2345bytes which still exceeded migrations.maxReadBatchSizeBytes. Increase migrations.maxReadBatchSizeBytes and try again."` - ); + expect(newState).toMatchObject({ + controlState: 'FATAL', + batchSize: 1, + maxBatchSize: 1000, + reason: + 'After reducing the read batch size to a single document, the Elasticsearch response content length was 2345bytes which still exceeded migrations.maxReadBatchSizeBytes. Increase migrations.maxReadBatchSizeBytes and try again.', + }); }); it('REINDEX_SOURCE_TO_TEMP_READ -> REINDEX_SOURCE_TO_TEMP_CLOSE_PIT if no outdated documents to reindex', () => { @@ -2073,14 +2090,15 @@ describe('migrations v2 model', () => { const newState = model(state, res); expect(newState.controlState).toEqual('SET_TEMP_WRITE_BLOCK'); }); + test('DONE_REINDEXING_SYNC -> FATAL if the synchronization between migrators fails', () => { const res: ResponseType<'DONE_REINDEXING_SYNC'> = Either.left({ type: 'synchronization_failed', error: new Error('Other migrators failed to reach the synchronization point'), }); - const newState = model(state, res); + const newState = model(state, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); - expect((newState as FatalState).reason).toMatchInlineSnapshot( + expect(newState.reason).toMatchInlineSnapshot( `"An error occurred whilst waiting for other migrators to get to this step."` ); }); @@ -2177,6 +2195,7 @@ describe('migrations v2 model', () => { corruptDocumentIds: [], progress: createInitialProgress(), }; + test('REINDEX_SOURCE_TO_TEMP_INDEX_BULK -> REINDEX_SOURCE_TO_TEMP_READ if action succeeded', () => { const res: ResponseType<'REINDEX_SOURCE_TO_TEMP_INDEX_BULK'> = Either.right('bulk_index_succeeded'); @@ -2185,6 +2204,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('REINDEX_SOURCE_TO_TEMP_INDEX_BULK -> REINDEX_SOURCE_TO_TEMP_CLOSE_PIT if response is left target_index_had_write_block', () => { const res: ResponseType<'REINDEX_SOURCE_TO_TEMP_INDEX_BULK'> = Either.left({ type: 'target_index_had_write_block', @@ -2194,6 +2214,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('REINDEX_SOURCE_TO_TEMP_INDEX_BULK -> REINDEX_SOURCE_TO_TEMP_CLOSE_PIT if response is left index_not_found_exception', () => { const res: ResponseType<'REINDEX_SOURCE_TO_TEMP_INDEX_BULK'> = Either.left({ type: 'index_not_found_exception', @@ -2204,6 +2225,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('REINDEX_SOURCE_TO_TEMP_INDEX_BULK -> FATAL if action returns left request_entity_too_large_exception', () => { const res: ResponseType<'REINDEX_SOURCE_TO_TEMP_INDEX_BULK'> = Either.left({ type: 'request_entity_too_large_exception', @@ -2214,6 +2236,7 @@ describe('migrations v2 model', () => { `"While indexing a batch of saved objects, Elasticsearch returned a 413 Request Entity Too Large exception. Ensure that the Kibana configuration option 'migrations.maxBatchSizeBytes' is set to a value that is lower than or equal to the Elasticsearch 'http.max_content_length' configuration option."` ); }); + test('REINDEX_SOURCE_TO_TEMP_INDEX_BULK should throw a throwBadResponse error if action failed', () => { const res: ResponseType<'REINDEX_SOURCE_TO_TEMP_INDEX_BULK'> = Either.left({ type: 'retryable_es_client_error', @@ -2233,6 +2256,7 @@ describe('migrations v2 model', () => { sourceIndex: Option.some('.kibana') as Option.Some, sourceIndexMappings: Option.some({}) as Option.Some, }; + test('SET_TEMP_WRITE_BLOCK -> CLONE_TEMP_TO_TARGET when response is right', () => { const res: ResponseType<'SET_TEMP_WRITE_BLOCK'> = Either.right('set_write_block_succeeded'); const newState = model(state, res); @@ -2299,13 +2323,14 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toBe(0); expect(newState.retryDelay).toBe(0); }); + test('CLONE_TEMP_TO_TARGET -> FATAL if action fails with cluster_shard_limit_exceeded', () => { const res: ResponseType<'CLONE_TEMP_TO_TARGET'> = Either.left({ type: 'cluster_shard_limit_exceeded', }); - const newState = model(state, res); + const newState = model(state, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); - expect((newState as FatalState).reason).toMatchInlineSnapshot( + expect(newState.reason).toMatchInlineSnapshot( `"[cluster_shard_limit_exceeded] Upgrading Kibana requires adding a small number of new shards. Ensure that Kibana is able to add 10 more shards by increasing the cluster.max_shards_per_node setting, or removing indices to clear up resources. See clusterShardLimitExceeded"` ); }); @@ -2687,7 +2712,7 @@ describe('migrations v2 model', () => { it('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT if action succeeded', () => { const res: ResponseType<'REFRESH_TARGET'> = Either.right({ refreshed: true }); - const newState = model(state, res) as UpdateTargetMappingsPropertiesState; + const newState = model(state, res); expect(newState.controlState).toBe('OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT'); }); }); @@ -2716,6 +2741,7 @@ describe('migrations v2 model', () => { hasTransformedDocs: false, progress: createInitialProgress(), }; + describe('OUTDATED_DOCUMENTS_TRANSFORM if action succeeds', () => { test('OUTDATED_DOCUMENTS_TRANSFORM -> TRANSFORMED_DOCUMENTS_BULK_INDEX if action succeeds', () => { const res: ResponseType<'OUTDATED_DOCUMENTS_TRANSFORM'> = Either.right({ processedDocs }); @@ -2730,6 +2756,7 @@ describe('migrations v2 model', () => { expect(newState.retryDelay).toEqual(0); expect(newState.progress.processed).toBe(outdatedDocuments.length); }); + test('OUTDATED_DOCUMENTS_TRANSFORM -> OUTDATED_DOCUMENTS_SEARCH_READ if there are are existing documents that failed transformation', () => { const outdatedDocumentsTransformStateWithFailedDocuments: OutdatedDocumentsTransform = { ...outdatedDocumentsTransformState, @@ -2747,6 +2774,7 @@ describe('migrations v2 model', () => { expect(newState.retryDelay).toEqual(0); expect(newState.progress.processed).toBe(outdatedDocuments.length); }); + test('OUTDATED_DOCUMENTS_TRANSFORM -> OUTDATED_DOCUMENTS_SEARCH_READ if there are are existing documents that failed transformation because of transform errors', () => { const outdatedDocumentsTransformStateWithFailedDocuments: OutdatedDocumentsTransform = { ...outdatedDocumentsTransformState, @@ -2766,6 +2794,7 @@ describe('migrations v2 model', () => { expect(newState.progress.processed).toBe(outdatedDocuments.length); }); }); + describe('OUTDATED_DOCUMENTS_TRANSFORM if action fails', () => { test('OUTDATED_DOCUMENTS_TRANSFORM -> OUTDATED_DOCUMENTS_SEARCH_READ adding newly failed documents to state if documents failed the transform', () => { const res: ResponseType<'OUTDATED_DOCUMENTS_TRANSFORM'> = Either.left({ @@ -2782,6 +2811,7 @@ describe('migrations v2 model', () => { expect(newState.corruptDocumentIds).toEqual(corruptDocumentIds); expect(newState.progress.processed).toBe(outdatedDocuments.length); }); + test('OUTDATED_DOCUMENTS_TRANSFORM -> OUTDATED_DOCUMENTS_SEARCH_READ combines newly failed documents with those already on state if documents failed the transform', () => { const newFailedTransformDocumentIds = ['b:other', 'c:__']; const outdatedDocumentsTransformStateWithFailedDocuments: OutdatedDocumentsTransform = { @@ -2917,6 +2947,7 @@ describe('migrations v2 model', () => { }, }), }; + test('UPDATE_TARGET_MAPPINGS_PROPERTIES -> UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK', () => { const res: ResponseType<'UPDATE_TARGET_MAPPINGS_PROPERTIES'> = Either.right({ taskId: 'update target mappings task', @@ -2961,10 +2992,7 @@ describe('migrations v2 model', () => { message: '[timeout_exception] Timeout waiting for ...', type: 'wait_for_task_completion_timeout', }); - const newState = model( - updateTargetMappingsWaitForTaskState, - res - ) as UpdateTargetMappingsPropertiesWaitForTaskState; + const newState = model(updateTargetMappingsWaitForTaskState, res); expect(newState.controlState).toEqual('UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK'); expect(newState.retryCount).toEqual(1); expect(newState.retryDelay).toEqual(2000); @@ -2976,7 +3004,7 @@ describe('migrations v2 model', () => { message: '[timeout_exception] Timeout waiting for ...', type: 'wait_for_task_completion_timeout', }); - const newState = model(state, res) as UpdateTargetMappingsPropertiesWaitForTaskState; + const newState = model(state, res); expect(newState.controlState).toEqual('UPDATE_TARGET_MAPPINGS_PROPERTIES_WAIT_FOR_TASK'); expect(newState.retryCount).toEqual(2); expect(newState.retryDelay).toEqual(4000); @@ -3023,7 +3051,7 @@ describe('migrations v2 model', () => { versionIndexReadyActions, }, res - ) as PostInitState; + ); expect(newState.controlState).toEqual('MARK_VERSION_INDEX_READY'); expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); @@ -3041,14 +3069,14 @@ describe('migrations v2 model', () => { versionIndexReadyActions, }, res - ) as PostInitState; + ); expect(newState.controlState).toEqual('MARK_VERSION_INDEX_READY_SYNC'); expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); test('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE if none versionIndexReadyActions', () => { - const newState = model(сheckVersionIndexReadyActionsState, res) as PostInitState; + const newState = model(сheckVersionIndexReadyActionsState, res); expect(newState.controlState).toEqual('DONE'); expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); @@ -3066,6 +3094,7 @@ describe('migrations v2 model', () => { sourceIndex: Option.none as Option.None, targetIndex: '.kibana_7.11.0_001', }; + test('CREATE_NEW_TARGET -> CHECK_VERSION_INDEX_READY_ACTIONS', () => { const res: ResponseType<'CREATE_NEW_TARGET'> = Either.right('create_index_succeeded'); const newState = model(createNewTargetState, res); @@ -3073,6 +3102,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('CREATE_NEW_TARGET -> CREATE_NEW_TARGET if action fails with index_not_green_timeout', () => { const res: ResponseType<'CREATE_NEW_TARGET'> = Either.left({ message: '[index_not_green_timeout] Timeout waiting for ...', @@ -3083,6 +3113,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(1); expect(newState.retryDelay).toEqual(2000); }); + test('CREATE_NEW_TARGET -> CHECK_VERSION_INDEX_READY_ACTIONS resets the retry count and delay', () => { const res: ResponseType<'CREATE_NEW_TARGET'> = Either.right('create_index_succeeded'); const testState = { @@ -3096,13 +3127,14 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('CREATE_NEW_TARGET -> FATAL if action fails with cluster_shard_limit_exceeded', () => { const res: ResponseType<'CREATE_NEW_TARGET'> = Either.left({ type: 'cluster_shard_limit_exceeded', }); - const newState = model(createNewTargetState, res); + const newState = model(createNewTargetState, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); - expect((newState as FatalState).reason).toMatchInlineSnapshot( + expect(newState.reason).toMatchInlineSnapshot( `"[cluster_shard_limit_exceeded] Upgrading Kibana requires adding a small number of new shards. Ensure that Kibana is able to add 10 more shards by increasing the cluster.max_shards_per_node setting, or removing indices to clear up resources. See clusterShardLimitExceeded"` ); }); @@ -3118,6 +3150,7 @@ describe('migrations v2 model', () => { versionIndexReadyActions: aliasActions, targetIndex: '.kibana_7.11.0_001', }; + test('MARK_VERSION_INDEX_READY -> DONE if the action succeeded', () => { const res: ResponseType<'MARK_VERSION_INDEX_READY'> = Either.right( 'update_aliases_succeeded' @@ -3127,6 +3160,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('MARK_VERSION_INDEX_READY -> MARK_VERSION_INDEX_CONFLICT if another removed the current alias from the source index', () => { const res: ResponseType<'MARK_VERSION_INDEX_READY'> = Either.left({ type: 'alias_not_found_exception', @@ -3136,6 +3170,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('MARK_VERSION_INDEX_READY -> MARK_VERSION_INDEX_CONFLICT if another node removed the temporary index', () => { const res: ResponseType<'MARK_VERSION_INDEX_READY'> = Either.left({ type: 'index_not_found_exception', @@ -3158,6 +3193,7 @@ describe('migrations v2 model', () => { versionIndexReadyActions: aliasActions, targetIndex: '.kibana_7.11.0_001', }; + test('MARK_VERSION_INDEX_CONFLICT -> DONE if the current alias is pointing to the version alias', () => { const res: ResponseType<'MARK_VERSION_INDEX_READY_CONFLICT'> = Either.right({ '.kibana_7.11.0_001': { @@ -3179,6 +3215,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('MARK_VERSION_INDEX_READY_CONFLICT -> FATAL if the current alias is pointing to a different version index', () => { const res: ResponseType<'MARK_VERSION_INDEX_READY_CONFLICT'> = Either.right({ '.kibana_7.11.0_001': { @@ -3203,6 +3240,7 @@ describe('migrations v2 model', () => { expect(newState.retryCount).toEqual(0); expect(newState.retryDelay).toEqual(0); }); + test('MARK_VERSION_INDEX_READY_CONFLICT -> FATAL if the current alias is pointing to a multiple indices', () => { const res: ResponseType<'MARK_VERSION_INDEX_READY_CONFLICT'> = Either.right({ '.kibana_7.11.0_001': { 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 4f1f48444dc23..cf0fe5fa3396b 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 @@ -82,193 +82,181 @@ export const model = (currentState: State, resW: ResponseType): if (stateP.controlState === 'INIT') { const res = resW as ExcludeRetryableEsError>; - 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 ${stateP.migrationDocLinks.routingAllocationDisabled} for more information on how to resolve the issue.`; - return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); - } else { - throwBadResponse(stateP, left); - } - } else if (Either.isRight(res)) { - // cluster routing allocation is enabled and we can continue with the migration as normal - const indices = res.right; - const aliasesRes = getAliases(indices); + // cluster routing allocation is enabled and we can continue with the migration as normal + const indices = res.right; + const aliasesRes = getAliases(indices); - if (Either.isLeft(aliasesRes)) { - return { - ...stateP, - controlState: 'FATAL', - reason: `The ${ - aliasesRes.left.alias - } alias is pointing to multiple indices: ${aliasesRes.left.indices.join(',')}.`, - }; - } + if (Either.isLeft(aliasesRes)) { + return { + ...stateP, + controlState: 'FATAL', + reason: `The ${ + aliasesRes.left.alias + } alias is pointing to multiple indices: ${aliasesRes.left.indices.join(',')}.`, + }; + } - const aliases = aliasesRes.right; + const aliases = aliasesRes.right; - if ( - // `.kibana` is pointing to an index that belongs to a later - // version of Kibana .e.g. a 7.11.0 instance found the `.kibana` alias - // pointing to `.kibana_7.12.0_001` - indexBelongsToLaterVersion(stateP.kibanaVersion, aliases[stateP.currentAlias]) - ) { - return { - ...stateP, - controlState: 'FATAL', - reason: `The ${ - stateP.currentAlias - } alias is pointing to a newer version of Kibana: v${indexVersion( - aliases[stateP.currentAlias] - )}`, - }; - } + if ( + // `.kibana` is pointing to an index that belongs to a later + // version of Kibana .e.g. a 7.11.0 instance found the `.kibana` alias + // pointing to `.kibana_7.12.0_001` + indexBelongsToLaterVersion(stateP.kibanaVersion, aliases[stateP.currentAlias]) + ) { + return { + ...stateP, + controlState: 'FATAL', + reason: `The ${ + stateP.currentAlias + } alias is pointing to a newer version of Kibana: v${indexVersion( + aliases[stateP.currentAlias] + )}`, + }; + } - const laterVersionAlias = hasLaterVersionAlias(stateP.kibanaVersion, aliases); - if ( - // a `.kibana_` alias exist, which refers to a later version of Kibana - // e.g. `.kibana_8.7.0` exists, and current stack version is 8.6.1 - // see https://github.com/elastic/kibana/issues/155136 - laterVersionAlias - ) { - return { - ...stateP, - controlState: 'FATAL', - reason: `The ${laterVersionAlias} alias refers to a newer version of Kibana: v${aliasVersion( - laterVersionAlias - )}`, - }; - } + const laterVersionAlias = hasLaterVersionAlias(stateP.kibanaVersion, aliases); + if ( + // a `.kibana_` alias exist, which refers to a later version of Kibana + // e.g. `.kibana_8.7.0` exists, and current stack version is 8.6.1 + // see https://github.com/elastic/kibana/issues/155136 + laterVersionAlias + ) { + return { + ...stateP, + controlState: 'FATAL', + reason: `The ${laterVersionAlias} alias refers to a newer version of Kibana: v${aliasVersion( + laterVersionAlias + )}`, + }; + } - // The source index .kibana is pointing to. E.g: ".kibana_8.7.0_001" - const source = aliases[stateP.currentAlias]; - // The target index .kibana WILL be pointing to if we reindex. E.g: ".kibana_8.8.0_001" - const newVersionTarget = stateP.versionIndex; + // The source index .kibana is pointing to. E.g: ".kibana_8.7.0_001" + const source = aliases[stateP.currentAlias]; + // The target index .kibana WILL be pointing to if we reindex. E.g: ".kibana_8.8.0_001" + const newVersionTarget = stateP.versionIndex; - const postInitState = { - aliases, - sourceIndex: Option.fromNullable(source), - sourceIndexMappings: Option.fromNullable(source ? indices[source]?.mappings : undefined), - versionIndexReadyActions: Option.none, - }; + const postInitState = { + aliases, + sourceIndex: Option.fromNullable(source), + sourceIndexMappings: Option.fromNullable(source ? indices[source]?.mappings : undefined), + versionIndexReadyActions: Option.none, + }; - if ( - // Don't actively participate in this migration but wait for another instance to complete it - stateP.waitForMigrationCompletion === true - ) { - return { - ...stateP, - ...postInitState, - sourceIndex: Option.none, - targetIndex: newVersionTarget, - controlState: 'WAIT_FOR_MIGRATION_COMPLETION', - // Wait for 2s before checking again if the migration has completed - retryDelay: 2000, - logs: [ - ...stateP.logs, - { - level: 'info', - message: `Migration required. Waiting until another Kibana instance completes the migration.`, - }, - ], - }; - } else if ( - // If the `.kibana` alias exists - Option.isSome(postInitState.sourceIndex) - ) { - return { - ...stateP, - ...postInitState, - controlState: 'WAIT_FOR_YELLOW_SOURCE', - sourceIndex: postInitState.sourceIndex, - sourceIndexMappings: postInitState.sourceIndexMappings as Option.Some, - targetIndex: postInitState.sourceIndex.value, // We preserve the same index, source == target (E.g: ".xx8.7.0_001") - }; - } else if (indices[stateP.legacyIndex] != null) { - // Migrate from a legacy index + if ( + // Don't actively participate in this migration but wait for another instance to complete it + stateP.waitForMigrationCompletion === true + ) { + return { + ...stateP, + ...postInitState, + sourceIndex: Option.none, + targetIndex: newVersionTarget, + controlState: 'WAIT_FOR_MIGRATION_COMPLETION', + // Wait for 2s before checking again if the migration has completed + retryDelay: 2000, + logs: [ + ...stateP.logs, + { + level: 'info', + message: `Migration required. Waiting until another Kibana instance completes the migration.`, + }, + ], + }; + } else if ( + // If the `.kibana` alias exists + Option.isSome(postInitState.sourceIndex) + ) { + return { + ...stateP, + ...postInitState, + controlState: 'WAIT_FOR_YELLOW_SOURCE', + sourceIndex: postInitState.sourceIndex, + sourceIndexMappings: postInitState.sourceIndexMappings as Option.Some, + targetIndex: postInitState.sourceIndex.value, // We preserve the same index, source == target (E.g: ".xx8.7.0_001") + }; + } else if (indices[stateP.legacyIndex] != null) { + // Migrate from a legacy index - // If the user used default index names we can narrow the version - // number we use when creating a backup index. This is purely to help - // users more easily identify how "old" and index is so that they can - // decide if it's safe to delete these rollback backups. Because - // backups are kept for rollback, a version number is more useful than - // a date. - let legacyVersion = ''; - if (stateP.indexPrefix === '.kibana') { - legacyVersion = 'pre6.5.0'; - } else if (stateP.indexPrefix === '.kibana_task_manager') { - legacyVersion = 'pre7.4.0'; - } else { - legacyVersion = 'pre' + stateP.kibanaVersion; - } + // If the user used default index names we can narrow the version + // number we use when creating a backup index. This is purely to help + // users more easily identify how "old" and index is so that they can + // decide if it's safe to delete these rollback backups. Because + // backups are kept for rollback, a version number is more useful than + // a date. + let legacyVersion = ''; + if (stateP.indexPrefix === '.kibana') { + legacyVersion = 'pre6.5.0'; + } else if (stateP.indexPrefix === '.kibana_task_manager') { + legacyVersion = 'pre7.4.0'; + } else { + legacyVersion = 'pre' + stateP.kibanaVersion; + } - const legacyReindexTarget = `${stateP.indexPrefix}_${legacyVersion}_001`; + const legacyReindexTarget = `${stateP.indexPrefix}_${legacyVersion}_001`; - return { - ...stateP, - ...postInitState, - controlState: 'LEGACY_SET_WRITE_BLOCK', - sourceIndex: Option.some(legacyReindexTarget) as Option.Some, - sourceIndexMappings: Option.some( - indices[stateP.legacyIndex].mappings - ) as Option.Some, - targetIndex: newVersionTarget, - legacyPreMigrationDoneActions: [ - { remove_index: { index: stateP.legacyIndex } }, - { - add: { - index: legacyReindexTarget, - alias: stateP.currentAlias, - }, + return { + ...stateP, + ...postInitState, + controlState: 'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION', + sourceIndex: Option.some(legacyReindexTarget) as Option.Some, + sourceIndexMappings: Option.some( + indices[stateP.legacyIndex].mappings + ) as Option.Some, + targetIndex: newVersionTarget, + legacyPreMigrationDoneActions: [ + { remove_index: { index: stateP.legacyIndex } }, + { + add: { + index: legacyReindexTarget, + alias: stateP.currentAlias, }, - ], - versionIndexReadyActions: Option.some([ - { - remove: { - index: legacyReindexTarget, - alias: stateP.currentAlias, - must_exist: true, - }, + }, + ], + versionIndexReadyActions: Option.some([ + { + remove: { + index: legacyReindexTarget, + alias: stateP.currentAlias, + must_exist: true, }, - { add: { index: newVersionTarget, alias: stateP.currentAlias } }, - { add: { index: newVersionTarget, alias: stateP.versionAlias } }, - { remove_index: { index: stateP.tempIndex } }, - ]), - }; - } else if ( - // if we must relocate documents to this migrator's index, but the index does NOT yet exist: - // this migrator must create a temporary index and synchronize with other migrators - // this is a similar flow to the reindex one, but this migrator will not reindexing anything - stateP.mustRelocateDocuments - ) { - return { - ...stateP, - ...postInitState, - controlState: 'CREATE_REINDEX_TEMP', - sourceIndex: Option.none as Option.None, - targetIndex: newVersionTarget, - versionIndexReadyActions: Option.some([ - { add: { index: newVersionTarget, alias: stateP.currentAlias } }, - { add: { index: newVersionTarget, alias: stateP.versionAlias } }, - { remove_index: { index: stateP.tempIndex } }, - ]), - }; - } else { - // no need to copy anything over from other indices, we can start with a clean, empty index - return { - ...stateP, - ...postInitState, - controlState: 'CREATE_NEW_TARGET', - sourceIndex: Option.none as Option.None, - targetIndex: newVersionTarget, - versionIndexReadyActions: Option.some([ - { add: { index: newVersionTarget, alias: stateP.currentAlias } }, - { add: { index: newVersionTarget, alias: stateP.versionAlias } }, - ]) as Option.Some, - }; - } + }, + { add: { index: newVersionTarget, alias: stateP.currentAlias } }, + { add: { index: newVersionTarget, alias: stateP.versionAlias } }, + { remove_index: { index: stateP.tempIndex } }, + ]), + }; + } else if ( + // if we must relocate documents to this migrator's index, but the index does NOT yet exist: + // this migrator must create a temporary index and synchronize with other migrators + // this is a similar flow to the reindex one, but this migrator will not reindexing anything + stateP.mustRelocateDocuments + ) { + return { + ...stateP, + ...postInitState, + controlState: 'CREATE_REINDEX_TEMP', + sourceIndex: Option.none as Option.None, + targetIndex: newVersionTarget, + versionIndexReadyActions: Option.some([ + { add: { index: newVersionTarget, alias: stateP.currentAlias } }, + { add: { index: newVersionTarget, alias: stateP.versionAlias } }, + { remove_index: { index: stateP.tempIndex } }, + ]), + }; } else { - throwBadResponse(stateP, res); + // no need to copy anything over from other indices, we can start with a clean, empty index + return { + ...stateP, + ...postInitState, + controlState: 'CREATE_NEW_TARGET', + sourceIndex: Option.none as Option.None, + targetIndex: newVersionTarget, + versionIndexReadyActions: Option.some([ + { add: { index: newVersionTarget, alias: stateP.currentAlias } }, + { add: { index: newVersionTarget, alias: stateP.versionAlias } }, + ]) as Option.Some, + }; } } else if (stateP.controlState === 'WAIT_FOR_MIGRATION_COMPLETION') { const res = resW as ExcludeRetryableEsError>; @@ -306,6 +294,22 @@ export const model = (currentState: State, resW: ResponseType): ], }; } + } else if (stateP.controlState === 'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION') { + const res = resW as ExcludeRetryableEsError>; + if (Either.isRight(res)) { + return { + ...stateP, + controlState: 'LEGACY_SET_WRITE_BLOCK', + }; + } else { + 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 ${stateP.migrationDocLinks.routingAllocationDisabled} for more information on how to resolve the issue.`; + return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); + } else { + throwBadResponse(stateP, left); + } + } } else if (stateP.controlState === 'LEGACY_SET_WRITE_BLOCK') { const res = resW as ExcludeRetryableEsError>; // If the write block is successfully in place @@ -457,7 +461,7 @@ export const model = (currentState: State, resW: ResponseType): // we must reindex and synchronize with other migrators return { ...stateP, - controlState: 'CHECK_UNKNOWN_DOCUMENTS', + controlState: 'CHECK_CLUSTER_ROUTING_ALLOCATION', }; } else { // this migrator is not involved in a relocation, we can proceed with the standard flow @@ -502,7 +506,7 @@ export const model = (currentState: State, resW: ResponseType): case MigrationType.Incompatible: return { ...stateP, - controlState: 'CHECK_UNKNOWN_DOCUMENTS', + controlState: 'CHECK_CLUSTER_ROUTING_ALLOCATION', }; case MigrationType.Unnecessary: return { @@ -636,7 +640,7 @@ export const model = (currentState: State, resW: ResponseType): ...stateP, controlState: stateP.mustRefresh ? 'REFRESH_SOURCE' : 'OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT', }; - } else if (Either.isLeft(res)) { + } else { const left = res.left; // 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. @@ -661,11 +665,8 @@ export const model = (currentState: State, resW: ResponseType): // step). throwBadResponse(stateP, left as never); } else { - // TODO update to handle 2 more cases throwBadResponse(stateP, left); } - } else { - throwBadResponse(stateP, res); } } else if (stateP.controlState === 'REFRESH_SOURCE') { const res = resW as ExcludeRetryableEsError>; @@ -677,6 +678,22 @@ export const model = (currentState: State, resW: ResponseType): } else { throwBadResponse(stateP, res); } + } else if (stateP.controlState === 'CHECK_CLUSTER_ROUTING_ALLOCATION') { + const res = resW as ExcludeRetryableEsError>; + if (Either.isRight(res)) { + return { + ...stateP, + controlState: 'CHECK_UNKNOWN_DOCUMENTS', + }; + } else { + 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 ${stateP.migrationDocLinks.routingAllocationDisabled} for more information on how to resolve the issue.`; + return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); + } else { + throwBadResponse(stateP, left); + } + } } else if (stateP.controlState === 'CHECK_UNKNOWN_DOCUMENTS') { const res = resW as ExcludeRetryableEsError>; @@ -1304,11 +1321,11 @@ export const model = (currentState: State, resW: ResponseType): 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 ) { + // we might have some transformation errors from previous iterations, but user has chosen to discard them const documents = Either.isRight(res) ? res.right.processedDocs : res.left.processedDocs; let corruptDocumentIds = stateP.corruptDocumentIds; @@ -1346,8 +1363,10 @@ export const model = (currentState: State, resW: ResponseType): }; } } else { - // We have seen corrupt documents and/or transformation errors - // skip indexing and go straight to reading and transforming more docs + // At this point, there are some corrupt documents and/or transformation errors + // from previous iterations and we're not discarding them. + // Also, the current batch of SEARCH_READ documents has been transformed successfully + // so there is no need to append them to the lists of corruptDocumentIds, transformErrors. return { ...stateP, controlState: 'OUTDATED_DOCUMENTS_SEARCH_READ', 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 9f7da4a10c2e8..2ab4a0d927b84 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 @@ -80,7 +80,7 @@ export const nextActionMap = ( ) => { return { INIT: (state: InitState) => - Actions.initAction({ client, indices: [state.currentAlias, state.versionAlias] }), + Actions.fetchIndices({ client, indices: [state.currentAlias, state.versionAlias] }), WAIT_FOR_MIGRATION_COMPLETION: (state: WaitForMigrationCompletionState) => Actions.fetchIndices({ client, indices: [state.currentAlias, state.versionAlias] }), WAIT_FOR_YELLOW_SOURCE: (state: WaitForYellowSourceState) => @@ -117,6 +117,7 @@ export const nextActionMap = ( Actions.updateAliases({ client, aliasActions: state.preTransformDocsActions }), REFRESH_SOURCE: (state: RefreshSource) => Actions.refreshIndex({ client, index: state.sourceIndex.value }), + CHECK_CLUSTER_ROUTING_ALLOCATION: () => Actions.checkClusterRoutingAllocationEnabled(client), CHECK_UNKNOWN_DOCUMENTS: (state: CheckUnknownDocumentsState) => Actions.checkForUnknownDocs({ client, @@ -287,6 +288,8 @@ export const nextActionMap = ( ), MARK_VERSION_INDEX_READY_CONFLICT: (state: MarkVersionIndexReadyConflict) => Actions.fetchIndices({ client, indices: [state.currentAlias, state.versionAlias] }), + LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION: () => + Actions.checkClusterRoutingAllocationEnabled(client), LEGACY_SET_WRITE_BLOCK: (state: LegacySetWriteBlockState) => Actions.setWriteBlock({ client, index: state.legacyIndex }), LEGACY_CREATE_REINDEX_TARGET: (state: LegacyCreateReindexTargetState) => 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 b26088adc53e9..fc32f88ddd910 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 @@ -384,6 +384,10 @@ export interface RefreshTarget extends PostInitState { readonly targetIndex: string; } +export interface CheckClusterRoutingAllocationState extends SourceExistsState { + readonly controlState: 'CHECK_CLUSTER_ROUTING_ALLOCATION'; +} + export interface CheckTargetTypesMappingsState extends PostInitState { readonly controlState: 'CHECK_TARGET_MAPPINGS'; } @@ -510,6 +514,10 @@ export interface LegacyBaseState extends SourceExistsState { readonly legacyPreMigrationDoneActions: AliasAction[]; } +export interface LegacyCheckClusterRoutingAllocationState extends LegacyBaseState { + readonly controlState: 'LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION'; +} + export interface LegacySetWriteBlockState extends LegacyBaseState { /** Set a write block on the legacy index to prevent any further writes */ readonly controlState: 'LEGACY_SET_WRITE_BLOCK'; @@ -549,6 +557,7 @@ export interface LegacyDeleteState extends LegacyBaseState { export type State = Readonly< | CalculateExcludeFiltersState + | CheckClusterRoutingAllocationState | CheckTargetTypesMappingsState | CheckUnknownDocumentsState | CheckVersionIndexReadyActions @@ -561,6 +570,7 @@ export type State = Readonly< | DoneState | FatalState | InitState + | LegacyCheckClusterRoutingAllocationState | LegacyCreateReindexTargetState | LegacyDeleteState | LegacyReindexState 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 index a3db45a3748cc..c586d9f3b95df 100644 --- 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 @@ -9,7 +9,7 @@ import type { ActionErrorTypeMap as BaseActionErrorTypeMap } from '../../actions'; export { - initAction as init, + fetchIndices, waitForIndexStatus, createIndex, updateAliases, @@ -25,7 +25,6 @@ export { transformDocs, bulkOverwriteTransformedDocuments, noop, - type InitActionParams, type IncompatibleClusterRoutingAllocation, type RetryableEsClientError, type WaitForTaskCompletionTimeout, 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 index 0ba01a714b99d..36eb685226ce4 100644 --- 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 @@ -9,7 +9,7 @@ import './model.test.mocks'; import * as Either from 'fp-ts/lib/Either'; import { createContextMock, MockedMigratorContext } from '../test_helpers'; -import type { RetryableEsClientError } from '../../actions'; +import type { FetchIndexResponse, RetryableEsClientError } from '../../actions'; import type { State, BaseState, FatalState, AllActionStates } from '../state'; import type { StateActionResponse } from './types'; import { model, modelStageMap } from './model'; @@ -89,7 +89,7 @@ describe('model', () => { mappings: { properties: {} }, settings: {}, }, - }); + }) as Either.Right; const newState = model(state, res, context); expect(newState.retryCount).toEqual(0); 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 index 892ac57c7e79c..383b8dd583d41 100644 --- 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 @@ -75,24 +75,12 @@ describe('Stage: init', () => { }); }); - it('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); - }); - it('calls getCurrentIndex with the correct parameters', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; const aliases = { '.foo': '.bar' }; getAliasesMock.mockReturnValue(Either.right(aliases)); @@ -110,7 +98,9 @@ describe('Stage: init', () => { it('calls checkVersionCompatibility with the correct parameters', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; init(state, res, context); @@ -130,7 +120,9 @@ describe('Stage: init', () => { it('adds a log entry about the algo check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; const newState = init(state, res, context); @@ -142,7 +134,9 @@ describe('Stage: init', () => { it('INIT -> FATAL', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; const newState = init(state, res, context); @@ -162,7 +156,9 @@ describe('Stage: init', () => { it('adds a log entry about the algo check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; const newState = init(state, res, context); @@ -174,7 +170,9 @@ describe('Stage: init', () => { it('INIT -> FATAL', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; const newState = init(state, res, context); @@ -195,7 +193,9 @@ describe('Stage: init', () => { it('calls buildIndexMappings with the correct parameters', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; init(state, res, context); @@ -207,7 +207,9 @@ describe('Stage: init', () => { it('adds a log entry about the algo check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; const newState = init(state, res, context); @@ -219,7 +221,9 @@ describe('Stage: init', () => { it('INIT -> UPDATE_INDEX_MAPPINGS', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; const mockMappings = { properties: { someMappings: 'string' } }; buildIndexMappingsMock.mockReturnValue(mockMappings); @@ -248,7 +252,9 @@ describe('Stage: init', () => { it('adds a log entry about the algo check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; const newState = init(state, res, context); @@ -260,7 +266,9 @@ describe('Stage: init', () => { it('INIT -> UPDATE_INDEX_MAPPINGS', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; const mockMappings = { properties: { someMappings: 'string' } }; buildIndexMappingsMock.mockReturnValue(mockMappings); @@ -285,7 +293,9 @@ describe('Stage: init', () => { it('adds a log entry about the algo check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; const newState = init(state, res, context); @@ -302,7 +312,9 @@ describe('Stage: init', () => { it('calls buildIndexMappings with the correct parameters', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; init(state, res, context); @@ -315,7 +327,9 @@ describe('Stage: init', () => { it('calls getCreationAliases with the correct parameters', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; init(state, res, context); @@ -329,7 +343,9 @@ describe('Stage: init', () => { it('INIT -> CREATE_TARGET_INDEX', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; const mockMappings = { properties: { someMappings: 'string' } }; buildIndexMappingsMock.mockReturnValue(mockMappings); @@ -354,7 +370,9 @@ describe('Stage: init', () => { it('calls generateAdditiveMappingDiff with the correct parameters', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'greater', @@ -373,7 +391,9 @@ describe('Stage: init', () => { it('INIT -> UPDATE_INDEX_MAPPINGS', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'greater', @@ -396,7 +416,9 @@ describe('Stage: init', () => { it('adds a log entry about the version check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'greater', @@ -414,7 +436,9 @@ describe('Stage: init', () => { it('INIT -> UPDATE_ALIASES if alias actions are not empty', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'equal', @@ -437,7 +461,9 @@ describe('Stage: init', () => { it('INIT -> INDEX_STATE_UPDATE_DONE if alias actions are empty', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'equal', @@ -459,7 +485,9 @@ describe('Stage: init', () => { it('adds a log entry about the version check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'equal', @@ -477,7 +505,9 @@ describe('Stage: init', () => { it('INIT -> INDEX_STATE_UPDATE_DONE', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'lesser', @@ -494,7 +524,9 @@ describe('Stage: init', () => { it('adds a log entry about the version check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'lesser', @@ -512,7 +544,9 @@ describe('Stage: init', () => { it('INIT -> FATAL', () => { const state = createState(); const fetchIndexResponse = createResponse(); - const res: StateActionResponse<'INIT'> = Either.right(fetchIndexResponse); + const res: StateActionResponse<'INIT'> = Either.right( + fetchIndexResponse + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'conflict', @@ -530,7 +564,9 @@ describe('Stage: init', () => { it('adds a log entry about the version check', () => { const state = createState(); - const res: StateActionResponse<'INIT'> = Either.right(createResponse()); + const res: StateActionResponse<'INIT'> = Either.right( + createResponse() + ) as Either.Right; checkVersionCompatibilityMock.mockReturnValue({ status: 'conflict', 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 index 7405515c88b56..317090b41354b 100644 --- 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 @@ -8,10 +8,7 @@ import { cloneDeep } from 'lodash'; import * as Either from 'fp-ts/lib/Either'; -import { delayRetryState } from '../../../model/retry_state'; -import { throwBadResponse } from '../../../model/helpers'; import type { MigrationLog } from '../../../types'; -import { isTypeof } from '../../actions'; import { getAliases } from '../../../model/helpers'; import { getCurrentIndex, @@ -33,16 +30,6 @@ export const init: ModelStage< | 'INDEX_STATE_UPDATE_DONE' | 'FATAL' > = (state, res, context) => { - 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); - } - } - const types = context.types.map((type) => context.typeRegistry.getType(type)!); const logs: MigrationLog[] = [...state.logs]; 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 index 3073dd66e73f1..56ebb8d721cfa 100644 --- 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 @@ -57,7 +57,7 @@ export const nextActionMap = (context: MigratorContext) => { const client = context.elasticsearchClient; return { INIT: (state: InitState) => - Actions.init({ + Actions.fetchIndices({ client, indices: [`${context.indexPrefix}_*`], }), 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 2b6c7136519ff..64342b3b63d1f 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 @@ -39,11 +39,12 @@ import { removeWriteBlock, transformDocs, waitForIndexStatus, - initAction, + fetchIndices, cloneIndex, type DocumentsTransformFailed, type DocumentsTransformSuccess, createBulkIndexOperationTuple, + checkClusterRoutingAllocationEnabled, } from '@kbn/core-saved-objects-migration-server-internal'; const { startES } = createTestServers({ @@ -132,7 +133,7 @@ describe('migration actions', () => { await esServer.stop(); }); - describe('initAction', () => { + describe('fetchIndices', () => { afterAll(async () => { await client.cluster.putSettings({ body: { @@ -145,7 +146,7 @@ describe('migration actions', () => { }); it('resolves right empty record if no indices were found', async () => { expect.assertions(1); - const task = initAction({ client, indices: ['no_such_index'] }); + const task = fetchIndices({ client, indices: ['no_such_index'] }); await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", @@ -155,7 +156,7 @@ describe('migration actions', () => { }); it('resolves right record with found indices', async () => { expect.assertions(1); - const res = (await initAction({ + const res = (await fetchIndices({ client, indices: ['no_such_index', 'existing_index_with_docs'], })()) as Either.Right; @@ -174,7 +175,7 @@ describe('migration actions', () => { }); it('includes the _meta data of the indices in the response', async () => { expect.assertions(1); - const res = (await initAction({ + const res = (await fetchIndices({ client, indices: ['existing_index_with_docs'], })()) as Either.Right; @@ -200,6 +201,9 @@ describe('migration actions', () => { }) ); }); + }); + + describe('checkClusterRoutingAllocation', () => { it('resolves left when cluster.routing.allocation.enabled is incompatible', async () => { expect.assertions(3); await client.cluster.putSettings({ @@ -210,10 +214,7 @@ describe('migration actions', () => { }, }, }); - const task = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task = checkClusterRoutingAllocationEnabled(client); await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -230,10 +231,7 @@ describe('migration actions', () => { }, }, }); - const task2 = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task2 = checkClusterRoutingAllocationEnabled(client); await expect(task2()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -250,10 +248,7 @@ describe('migration actions', () => { }, }, }); - const task3 = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task3 = checkClusterRoutingAllocationEnabled(client); await expect(task3()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -272,10 +267,7 @@ describe('migration actions', () => { }, }, }); - const task = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task = checkClusterRoutingAllocationEnabled(client); const result = await task(); expect(Either.isRight(result)).toBe(true); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts index c114293823cb7..92b470288d327 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts @@ -39,11 +39,12 @@ import { removeWriteBlock, transformDocs, waitForIndexStatus, - initAction, + fetchIndices, cloneIndex, type DocumentsTransformFailed, type DocumentsTransformSuccess, createBulkIndexOperationTuple, + checkClusterRoutingAllocationEnabled, } from '@kbn/core-saved-objects-migration-server-internal'; interface EsServer { @@ -169,7 +170,7 @@ export const runActionTestSuite = ({ await esServer.stop(); }); - describe('initAction', () => { + describe('fetchIndices', () => { afterAll(async () => { await client.cluster.putSettings({ body: { @@ -182,7 +183,7 @@ export const runActionTestSuite = ({ }); it('resolves right empty record if no indices were found', async () => { expect.assertions(1); - const task = initAction({ client, indices: ['no_such_index'] }); + const task = fetchIndices({ client, indices: ['no_such_index'] }); await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Right", @@ -192,7 +193,7 @@ export const runActionTestSuite = ({ }); it('resolves right record with found indices', async () => { expect.assertions(1); - const res = (await initAction({ + const res = (await fetchIndices({ client, indices: ['no_such_index', 'existing_index_with_docs'], })()) as Either.Right; @@ -211,7 +212,7 @@ export const runActionTestSuite = ({ }); it('includes the _meta data of the indices in the response', async () => { expect.assertions(1); - const res = (await initAction({ + const res = (await fetchIndices({ client, indices: ['existing_index_with_docs'], })()) as Either.Right; @@ -237,6 +238,9 @@ export const runActionTestSuite = ({ }) ); }); + }); + + describe('checkClusterRoutingAllocation', () => { it('resolves left when cluster.routing.allocation.enabled is incompatible', async () => { expect.assertions(3); await client.cluster.putSettings({ @@ -247,10 +251,7 @@ export const runActionTestSuite = ({ }, }, }); - const task = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task = checkClusterRoutingAllocationEnabled(client); await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -267,10 +268,7 @@ export const runActionTestSuite = ({ }, }, }); - const task2 = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task2 = checkClusterRoutingAllocationEnabled(client); await expect(task2()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -287,10 +285,7 @@ export const runActionTestSuite = ({ }, }, }); - const task3 = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task3 = checkClusterRoutingAllocationEnabled(client); await expect(task3()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -309,10 +304,7 @@ export const runActionTestSuite = ({ }, }, }); - const task = initAction({ - client, - indices: ['existing_index_with_docs'], - }); + const task = checkClusterRoutingAllocationEnabled(client); const result = await task(); expect(Either.isRight(result)).toBe(true); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group5/active_delete.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group5/active_delete.test.ts index 37bd9f49a6cd1..d950129dac69a 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group5/active_delete.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group5/active_delete.test.ts @@ -366,7 +366,10 @@ describe('when upgrading to a new stack version', () => { const logs = await readLog(); expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS_PROPERTIES.'); - expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS_PROPERTIES -> CHECK_UNKNOWN_DOCUMENTS.'); + expect(logs).toMatch( + 'UPDATE_SOURCE_MAPPINGS_PROPERTIES -> CHECK_CLUSTER_ROUTING_ALLOCATION.' + ); + expect(logs).toMatch('CHECK_CLUSTER_ROUTING_ALLOCATION -> CHECK_UNKNOWN_DOCUMENTS.'); expect(logs).toMatch('CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK.'); expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_PROPERTIES.'); expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts index c0a4c73b1664c..8f765010e37a8 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts @@ -306,7 +306,8 @@ describe('split .kibana index into multiple system indices', () => { expect(logs).toContainLogEntries( [ // .kibana_task_manager index exists and has no aliases => LEGACY_* migration path - '[.kibana_task_manager] INIT -> LEGACY_SET_WRITE_BLOCK.', + '[.kibana_task_manager] INIT -> LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION.', + '[.kibana_task_manager] LEGACY_CHECK_CLUSTER_ROUTING_ALLOCATION -> LEGACY_SET_WRITE_BLOCK.', '[.kibana_task_manager] LEGACY_REINDEX_WAIT_FOR_TASK -> LEGACY_DELETE.', '[.kibana_task_manager] LEGACY_DELETE -> SET_SOURCE_WRITE_BLOCK.', '[.kibana_task_manager] SET_SOURCE_WRITE_BLOCK -> CALCULATE_EXCLUDE_FILTERS.', @@ -360,7 +361,8 @@ describe('split .kibana index into multiple system indices', () => { expect(logs).toContainLogEntries( [ '[.kibana] INIT -> WAIT_FOR_YELLOW_SOURCE.', - '[.kibana] WAIT_FOR_YELLOW_SOURCE -> CHECK_UNKNOWN_DOCUMENTS.', + '[.kibana] WAIT_FOR_YELLOW_SOURCE -> CHECK_CLUSTER_ROUTING_ALLOCATION.', + '[.kibana] CHECK_CLUSTER_ROUTING_ALLOCATION -> CHECK_UNKNOWN_DOCUMENTS.', '[.kibana] CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK.', '[.kibana] SET_SOURCE_WRITE_BLOCK -> CALCULATE_EXCLUDE_FILTERS.', '[.kibana] CALCULATE_EXCLUDE_FILTERS -> CREATE_REINDEX_TEMP.', diff --git a/src/core/server/integration_tests/saved_objects/migrations/group5/skip_reindex.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group5/skip_reindex.test.ts index 3d383a603a53f..4d244314d3acb 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group5/skip_reindex.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group5/skip_reindex.test.ts @@ -104,7 +104,10 @@ describe('when migrating to a new version', () => { const logs = await readLog(); expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS_PROPERTIES.'); - expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS_PROPERTIES -> CHECK_UNKNOWN_DOCUMENTS.'); + expect(logs).toMatch( + 'UPDATE_SOURCE_MAPPINGS_PROPERTIES -> CHECK_CLUSTER_ROUTING_ALLOCATION.' + ); + expect(logs).toMatch('CHECK_CLUSTER_ROUTING_ALLOCATION -> CHECK_UNKNOWN_DOCUMENTS.'); expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_PROPERTIES.'); expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY.');